Shield Security for WordPress - Version 7.2.3

Version Description

  • Current Release = Released: 25th March, 2019 - Release Notes

  • (v.3) FIX: Unable to turn off the Abandoned Plugin scanner.

  • (v.3) FIX: Fix bug with some DNS lookup failures for some ISPs.

  • (v.3) FIX: Fix display notice for 'disallow file editing' setting when IP is whitelisted.

Download this release

Release Info

Developer paultgoodchild
Plugin Icon 128x128 Shield Security for WordPress
Version 7.2.3
Comparing to
See all releases

Code changes from version 7.1.2 to 7.2.3

Files changed (318) hide show
  1. icwp-plugin-controller.php +48 -46
  2. icwp-wpsf.php +1 -1
  3. plugin-spec.php +2 -2
  4. readme.txt +34 -10
  5. resources/css/plugin.css +6 -3
  6. src/common/icwp-data.php +0 -9
  7. src/common/icwp-edd.php +1 -1
  8. src/common/icwp-ip.php +2 -2
  9. src/common/icwp-optionsvo.php +10 -1
  10. src/common/icwp-serviceproviders.php +1 -1
  11. src/common/icwp-wpfunctions.php +1 -1
  12. src/config/feature-admin_access_restriction.php +1 -0
  13. src/config/feature-audit_trail.php +76 -1
  14. src/config/feature-autoupdates.php +2 -0
  15. src/config/feature-comments_filter.php +1 -0
  16. src/config/feature-email.php +2 -1
  17. src/config/feature-firewall.php +3 -0
  18. src/config/feature-hack_protect.php +27 -28
  19. src/config/feature-headers.php +1 -0
  20. src/config/feature-insights.php +2 -1
  21. src/config/feature-ips.php +1 -0
  22. src/config/feature-license.php +2 -1
  23. src/config/feature-lockdown.php +2 -0
  24. src/config/feature-login_protect.php +1 -0
  25. src/config/feature-mousetrap.php +162 -0
  26. src/config/feature-plugin.php +3 -4
  27. src/config/feature-sessions.php +2 -1
  28. src/config/feature-statistics.php +2 -1
  29. src/config/feature-traffic.php +1 -0
  30. src/config/feature-user_management.php +56 -1
  31. src/features/admin_access_restriction.php +21 -21
  32. src/features/audit_trail.php +94 -9
  33. src/features/autoupdates.php +6 -4
  34. src/features/base.php +29 -92
  35. src/features/base_wpsf.php +2 -2
  36. src/features/comments_filter.php +3 -1
  37. src/features/hack_protect.php +98 -102
  38. src/features/insights.php +24 -18
  39. src/features/ips.php +3 -4
  40. src/features/license.php +40 -47
  41. src/features/lockdown.php +4 -3
  42. src/features/login_protect.php +13 -14
  43. src/features/mousetrap.php +209 -0
  44. src/features/plugin.php +34 -35
  45. src/features/sessions.php +3 -2
  46. src/features/traffic.php +4 -4
  47. src/features/user_management.php +112 -36
  48. src/lib/src/ChangeTrack/Diff/Base.php +71 -0
  49. src/lib/src/ChangeTrack/Diff/DiffComments.php +20 -0
  50. src/lib/src/ChangeTrack/Diff/DiffMedia.php +6 -0
  51. src/lib/src/ChangeTrack/Diff/DiffPages.php +16 -0
  52. src/lib/src/ChangeTrack/Diff/DiffPlugins.php +18 -0
  53. src/lib/src/ChangeTrack/Diff/DiffPosts.php +18 -0
  54. src/lib/src/ChangeTrack/Diff/DiffThemes.php +20 -0
  55. src/lib/src/ChangeTrack/Diff/DiffUsers.php +17 -0
  56. src/lib/src/ChangeTrack/Report/Build/Base.php +75 -0
  57. src/lib/src/ChangeTrack/Report/Build/Comments.php +55 -0
  58. src/lib/src/ChangeTrack/Report/Build/Media.php +57 -0
  59. src/lib/src/ChangeTrack/Report/Build/Pages.php +61 -0
  60. src/lib/src/ChangeTrack/Report/Build/Plugins.php +61 -0
  61. src/lib/src/ChangeTrack/Report/Build/Posts.php +61 -0
  62. src/lib/src/ChangeTrack/Report/Build/Themes.php +61 -0
  63. src/lib/src/ChangeTrack/Report/Build/Users.php +58 -0
  64. src/lib/src/ChangeTrack/Snapshot/BuildComments.php +62 -0
  65. src/lib/src/ChangeTrack/Snapshot/BuildMedia.php +28 -0
  66. src/lib/src/ChangeTrack/Snapshot/BuildPages.php +36 -0
  67. src/lib/src/ChangeTrack/Snapshot/BuildPlugins.php +36 -0
  68. src/lib/src/ChangeTrack/Snapshot/BuildPosts.php +62 -0
  69. src/lib/src/ChangeTrack/Snapshot/BuildThemes.php +41 -0
  70. src/lib/src/ChangeTrack/Snapshot/BuildUsers.php +76 -0
  71. src/lib/src/ChangeTrack/Snapshot/Collate.php +27 -0
  72. src/lib/src/ChangeTrack/Snapshot/SnapshotsConsumer.php +62 -0
  73. src/lib/src/Databases/ChangeTracking/Delete.php +8 -0
  74. src/lib/src/Databases/ChangeTracking/EntryVO.php +56 -0
  75. src/lib/src/Databases/ChangeTracking/Handler.php +8 -0
  76. src/lib/src/Databases/ChangeTracking/Insert.php +18 -0
  77. src/lib/src/Databases/ChangeTracking/Select.php +9 -0
  78. src/lib/src/Databases/ChangeTracking/Update.php +8 -0
  79. src/lib/src/Modules/MouseTrap/Base.php +44 -0
  80. src/lib/src/Modules/MouseTrap/Detect404.php +34 -0
  81. src/lib/src/Modules/MouseTrap/DetectXmlRpc.php +36 -0
  82. src/lib/src/Modules/MouseTrap/FakeWebCrawler.php +62 -0
  83. src/lib/src/Modules/MouseTrap/InvalidUsername.php +55 -0
  84. src/lib/src/Modules/MouseTrap/LinkCheese.php +123 -0
  85. src/lib/src/Modules/UserManagement/Suspend/Base.php +37 -0
  86. src/lib/src/Modules/UserManagement/Suspend/Idle.php +53 -0
  87. src/lib/src/Modules/UserManagement/Suspend/PasswordExpiry.php +61 -0
  88. src/lib/src/Modules/UserManagement/Suspend/Suspended.php +25 -0
  89. src/lib/src/Modules/UserManagement/UpdateUserPasswordMeta.php +14 -0
  90. src/lib/src/Scans/Helpers/WpCoreFileDownload.php +1 -1
  91. src/lib/src/Scans/Wpv/Scanner.php +28 -21
  92. src/lib/src/Users/ShieldUserMeta.php +26 -0
  93. src/lib/vendor/composer/autoload_classmap.php +54 -0
  94. src/lib/vendor/composer/autoload_static.php +54 -0
  95. src/lib/vendor/composer/installed.json +193 -193
  96. src/lib/vendor/fernleafsystems/wordpress-services/src/Core/CoreFileHashes.php +2 -2
  97. src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Fs.php +40 -32
  98. src/lib/vendor/fernleafsystems/wordpress-services/src/Core/General.php +42 -38
  99. src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Plugins.php +13 -1
  100. src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Request.php +7 -0
  101. src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Respond.php +1 -1
  102. src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Response.php +14 -0
  103. src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Users.php +17 -1
  104. src/lib/vendor/fernleafsystems/wordpress-services/src/Services.php +10 -0
  105. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Data.php +9 -14
  106. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncrypt.php +176 -0
  107. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncryptVo.php +66 -0
  108. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/File/ReadDataFromFileEncrypted.php +42 -0
  109. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/File/TestFileWritable.php +62 -0
  110. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/File/WriteDataToFileEncrypted.php +35 -0
  111. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/HttpRequest.php +1 -1
  112. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/IpUtils.php +9 -5
  113. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Net/VisitorIpDetection.php +182 -0
  114. src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/ServiceProviders.php +43 -77
  115. src/lib/vendor/twig/twig/lib/Twig/Autoloader.php +3 -1
  116. src/lib/vendor/twig/twig/lib/Twig/BaseNodeVisitor.php +4 -47
  117. src/lib/vendor/twig/twig/lib/Twig/Cache/Filesystem.php +4 -84
  118. src/lib/vendor/twig/twig/lib/Twig/Cache/Null.php +4 -33
  119. src/lib/vendor/twig/twig/lib/Twig/CacheInterface.php +6 -53
  120. src/lib/vendor/twig/twig/lib/Twig/Compiler.php +4 -279
  121. src/lib/vendor/twig/twig/lib/Twig/ContainerRuntimeLoader.php +4 -32
  122. src/lib/vendor/twig/twig/lib/Twig/Environment.php +4 -1610
  123. src/lib/vendor/twig/twig/lib/Twig/Error.php +4 -326
  124. src/lib/vendor/twig/twig/lib/Twig/Error/Loader.php +5 -30
  125. src/lib/vendor/twig/twig/lib/Twig/Error/Runtime.php +7 -18
  126. src/lib/vendor/twig/twig/lib/Twig/Error/Syntax.php +4 -48
  127. src/lib/vendor/twig/twig/lib/Twig/ExistsLoaderInterface.php +7 -27
  128. src/lib/vendor/twig/twig/lib/Twig/ExpressionParser.php +4 -737
  129. src/lib/vendor/twig/twig/lib/Twig/Extension.php +4 -62
  130. src/lib/vendor/twig/twig/lib/Twig/Extension/Core.php +4 -1640
  131. src/lib/vendor/twig/twig/lib/Twig/Extension/Debug.php +4 -60
  132. src/lib/vendor/twig/twig/lib/Twig/Extension/Escaper.php +4 -105
  133. src/lib/vendor/twig/twig/lib/Twig/Extension/GlobalsInterface.php +7 -20
  134. src/lib/vendor/twig/twig/lib/Twig/Extension/InitRuntimeInterface.php +7 -20
  135. src/lib/vendor/twig/twig/lib/Twig/Extension/Optimizer.php +4 -28
  136. src/lib/vendor/twig/twig/lib/Twig/Extension/Profiler.php +4 -42
  137. src/lib/vendor/twig/twig/lib/Twig/Extension/Sandbox.php +4 -96
  138. src/lib/vendor/twig/twig/lib/Twig/Extension/Staging.php +4 -105
  139. src/lib/vendor/twig/twig/lib/Twig/Extension/StringLoader.php +4 -40
  140. src/lib/vendor/twig/twig/lib/Twig/ExtensionInterface.php +6 -85
  141. src/lib/vendor/twig/twig/lib/Twig/FactoryRuntimeLoader.php +4 -32
  142. src/lib/vendor/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php +5 -54
  143. src/lib/vendor/twig/twig/lib/Twig/Filter.php +6 -4
  144. src/lib/vendor/twig/twig/lib/Twig/Filter/Function.php +2 -2
  145. src/lib/vendor/twig/twig/lib/Twig/Filter/Method.php +6 -4
  146. src/lib/vendor/twig/twig/lib/Twig/Filter/Node.php +2 -2
  147. src/lib/vendor/twig/twig/lib/Twig/FilterCallableInterface.php +1 -1
  148. src/lib/vendor/twig/twig/lib/Twig/FilterInterface.php +4 -2
  149. src/lib/vendor/twig/twig/lib/Twig/Function.php +6 -4
  150. src/lib/vendor/twig/twig/lib/Twig/Function/Function.php +2 -2
  151. src/lib/vendor/twig/twig/lib/Twig/Function/Method.php +6 -4
  152. src/lib/vendor/twig/twig/lib/Twig/Function/Node.php +2 -2
  153. src/lib/vendor/twig/twig/lib/Twig/FunctionCallableInterface.php +1 -1
  154. src/lib/vendor/twig/twig/lib/Twig/FunctionInterface.php +4 -2
  155. src/lib/vendor/twig/twig/lib/Twig/Lexer.php +4 -420
  156. src/lib/vendor/twig/twig/lib/Twig/LexerInterface.php +8 -4
  157. src/lib/vendor/twig/twig/lib/Twig/Loader/Array.php +4 -90
  158. src/lib/vendor/twig/twig/lib/Twig/Loader/Chain.php +4 -144
  159. src/lib/vendor/twig/twig/lib/Twig/Loader/Filesystem.php +4 -291
  160. src/lib/vendor/twig/twig/lib/Twig/Loader/String.php +9 -4
  161. src/lib/vendor/twig/twig/lib/Twig/LoaderInterface.php +6 -52
  162. src/lib/vendor/twig/twig/lib/Twig/Markup.php +4 -32
  163. src/lib/vendor/twig/twig/lib/Twig/Node.php +4 -249
  164. src/lib/vendor/twig/twig/lib/Twig/Node/AutoEscape.php +4 -29
  165. src/lib/vendor/twig/twig/lib/Twig/Node/Block.php +4 -34
  166. src/lib/vendor/twig/twig/lib/Twig/Node/BlockReference.php +4 -27
  167. src/lib/vendor/twig/twig/lib/Twig/Node/Body.php +7 -17
  168. src/lib/vendor/twig/twig/lib/Twig/Node/CheckSecurity.php +4 -73
  169. src/lib/vendor/twig/twig/lib/Twig/Node/Deprecated.php +4 -42
  170. src/lib/vendor/twig/twig/lib/Twig/Node/Do.php +4 -28
  171. src/lib/vendor/twig/twig/lib/Twig/Node/Embed.php +4 -39
  172. src/lib/vendor/twig/twig/lib/Twig/Node/Expression.php +7 -18
  173. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Array.php +4 -76
  174. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/AssignName.php +5 -19
  175. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary.php +5 -31
  176. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Add.php +6 -15
  177. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/And.php +6 -15
  178. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php +6 -15
  179. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php +6 -15
  180. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php +6 -15
  181. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Concat.php +6 -15
  182. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Div.php +6 -15
  183. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php +5 -26
  184. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Equal.php +6 -14
  185. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php +5 -20
  186. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Greater.php +6 -14
  187. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php +6 -14
  188. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/In.php +5 -24
  189. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Less.php +6 -14
  190. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/LessEqual.php +6 -14
  191. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php +5 -24
  192. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mod.php +6 -15
  193. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mul.php +6 -15
  194. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotEqual.php +6 -14
  195. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php +5 -24
  196. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Or.php +6 -15
  197. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Power.php +4 -27
  198. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Range.php +5 -24
  199. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php +5 -26
  200. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Sub.php +6 -15
  201. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.php +4 -86
  202. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Call.php +4 -286
  203. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Conditional.php +5 -27
  204. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Constant.php +5 -19
  205. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php +5 -2
  206. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Filter.php +5 -35
  207. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Filter/Default.php +4 -38
  208. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Function.php +5 -39
  209. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php +4 -67
  210. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/MethodCall.php +4 -36
  211. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Name.php +4 -100
  212. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/NullCoalesce.php +4 -41
  213. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Parent.php +4 -37
  214. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/TempName.php +5 -22
  215. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test.php +4 -38
  216. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test/Constant.php +5 -42
  217. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.php +4 -54
  218. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test/Divisibleby.php +5 -29
  219. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test/Even.php +5 -28
  220. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test/Null.php +5 -27
  221. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test/Odd.php +5 -28
  222. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test/Sameas.php +5 -25
  223. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Unary.php +5 -23
  224. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Neg.php +6 -15
  225. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Not.php +6 -15
  226. src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Pos.php +6 -15
  227. src/lib/vendor/twig/twig/lib/Twig/Node/Flush.php +4 -26
  228. src/lib/vendor/twig/twig/lib/Twig/Node/For.php +4 -106
  229. src/lib/vendor/twig/twig/lib/Twig/Node/ForLoop.php +4 -45
  230. src/lib/vendor/twig/twig/lib/Twig/Node/If.php +4 -61
  231. src/lib/vendor/twig/twig/lib/Twig/Node/Import.php +4 -44
  232. src/lib/vendor/twig/twig/lib/Twig/Node/Include.php +4 -83
  233. src/lib/vendor/twig/twig/lib/Twig/Node/Macro.php +4 -118
  234. src/lib/vendor/twig/twig/lib/Twig/Node/Module.php +4 -459
  235. src/lib/vendor/twig/twig/lib/Twig/Node/Print.php +4 -29
  236. src/lib/vendor/twig/twig/lib/Twig/Node/Sandbox.php +4 -37
  237. src/lib/vendor/twig/twig/lib/Twig/Node/SandboxedPrint.php +4 -44
  238. src/lib/vendor/twig/twig/lib/Twig/Node/Set.php +4 -91
  239. src/lib/vendor/twig/twig/lib/Twig/Node/SetTemp.php +4 -33
  240. src/lib/vendor/twig/twig/lib/Twig/Node/Spaceless.php +4 -30
  241. src/lib/vendor/twig/twig/lib/Twig/Node/Text.php +4 -29
  242. src/lib/vendor/twig/twig/lib/Twig/Node/With.php +4 -57
  243. src/lib/vendor/twig/twig/lib/Twig/NodeCaptureInterface.php +7 -17
  244. src/lib/vendor/twig/twig/lib/Twig/NodeInterface.php +4 -2
  245. src/lib/vendor/twig/twig/lib/Twig/NodeOutputInterface.php +7 -17
  246. src/lib/vendor/twig/twig/lib/Twig/NodeTraverser.php +4 -79
  247. src/lib/vendor/twig/twig/lib/Twig/NodeVisitor/Escaper.php +4 -147
  248. src/lib/vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php +4 -246
  249. src/lib/vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php +4 -143
  250. src/lib/vendor/twig/twig/lib/Twig/NodeVisitor/Sandbox.php +4 -75
  251. src/lib/vendor/twig/twig/lib/Twig/NodeVisitorInterface.php +6 -40
  252. src/lib/vendor/twig/twig/lib/Twig/Parser.php +4 -409
  253. src/lib/vendor/twig/twig/lib/Twig/ParserInterface.php +7 -3
  254. src/lib/vendor/twig/twig/lib/Twig/Profiler/Dumper/Base.php +4 -55
  255. src/lib/vendor/twig/twig/lib/Twig/Profiler/Dumper/Blackfire.php +4 -65
  256. src/lib/vendor/twig/twig/lib/Twig/Profiler/Dumper/Html.php +4 -40
  257. src/lib/vendor/twig/twig/lib/Twig/Profiler/Dumper/Text.php +4 -28
  258. src/lib/vendor/twig/twig/lib/Twig/Profiler/Node/EnterProfile.php +4 -32
  259. src/lib/vendor/twig/twig/lib/Twig/Profiler/Node/LeaveProfile.php +4 -26
  260. src/lib/vendor/twig/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php +4 -60
  261. src/lib/vendor/twig/twig/lib/Twig/Profiler/Profile.php +4 -163
  262. src/lib/vendor/twig/twig/lib/Twig/RuntimeLoaderInterface.php +7 -25
  263. src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityError.php +7 -17
  264. src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php +4 -26
  265. src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php +4 -26
  266. src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedMethodError.php +4 -33
  267. src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedPropertyError.php +4 -33
  268. src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php +4 -26
  269. src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php +4 -118
  270. src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicyInterface.php +6 -21
  271. src/lib/vendor/twig/twig/lib/Twig/SimpleFilter.php +4 -114
  272. src/lib/vendor/twig/twig/lib/Twig/SimpleFunction.php +4 -104
  273. src/lib/vendor/twig/twig/lib/Twig/SimpleTest.php +4 -78
  274. src/lib/vendor/twig/twig/lib/Twig/Source.php +4 -46
  275. src/lib/vendor/twig/twig/lib/Twig/SourceContextLoaderInterface.php +7 -29
  276. src/lib/vendor/twig/twig/lib/Twig/Template.php +4 -697
  277. src/lib/vendor/twig/twig/lib/Twig/TemplateInterface.php +3 -1
  278. src/lib/vendor/twig/twig/lib/Twig/TemplateWrapper.php +4 -130
  279. src/lib/vendor/twig/twig/lib/Twig/Test.php +1 -1
  280. src/lib/vendor/twig/twig/lib/Twig/Token.php +4 -200
  281. src/lib/vendor/twig/twig/lib/Twig/TokenParser.php +4 -26
  282. src/lib/vendor/twig/twig/lib/Twig/TokenParser/AutoEscape.php +4 -76
  283. src/lib/vendor/twig/twig/lib/Twig/TokenParser/Block.php +4 -66
  284. src/lib/vendor/twig/twig/lib/Twig/TokenParser/Deprecated.php +4 -35
  285. src/lib/vendor/twig/twig/lib/Twig/TokenParser/Do.php +4 -27
  286. src/lib/vendor/twig/twig/lib/Twig/TokenParser/Embed.php +4 -60
  287. src/lib/vendor/twig/twig/lib/Twig/TokenParser/Extends.php +4 -39
  288. src/lib/vendor/twig/twig/lib/Twig/TokenParser/Filter.php +4 -46
  289. src/lib/vendor/twig/twig/lib/Twig/TokenParser/Flush.php +4 -27
  290. src/lib/vendor/twig/twig/lib/Twig/TokenParser/For.php +4 -120
  291. src/lib/vendor/twig/twig/lib/Twig/TokenParser/From.php +4 -59
  292. src/lib/vendor/twig/twig/lib/Twig/TokenParser/If.php +4 -79
  293. src/lib/vendor/twig/twig/lib/Twig/TokenParser/Import.php +4 -34
  294. src/lib/vendor/twig/twig/lib/Twig/TokenParser/Include.php +4 -58
  295. src/lib/vendor/twig/twig/lib/Twig/TokenParser/Macro.php +4 -53
  296. src/lib/vendor/twig/twig/lib/Twig/TokenParser/Sandbox.php +4 -54
  297. src/lib/vendor/twig/twig/lib/Twig/TokenParser/Set.php +4 -68
  298. src/lib/vendor/twig/twig/lib/Twig/TokenParser/Spaceless.php +4 -44
  299. src/lib/vendor/twig/twig/lib/Twig/TokenParser/Use.php +4 -63
  300. src/lib/vendor/twig/twig/lib/Twig/TokenParser/With.php +4 -45
  301. src/lib/vendor/twig/twig/lib/Twig/TokenParserBroker.php +11 -9
  302. src/lib/vendor/twig/twig/lib/Twig/TokenParserBrokerInterface.php +4 -2
  303. src/lib/vendor/twig/twig/lib/Twig/TokenParserInterface.php +6 -38
  304. src/lib/vendor/twig/twig/lib/Twig/TokenStream.php +4 -189
  305. src/lib/vendor/twig/twig/lib/Twig/Util/DeprecationCollector.php +4 -79
  306. src/lib/vendor/twig/twig/lib/Twig/Util/TemplateDirIterator.php +4 -21
  307. src/lib/vendor/twig/twig/src/Cache/CacheInterface.php +54 -5
  308. src/lib/vendor/twig/twig/src/Cache/FilesystemCache.php +85 -3
  309. src/lib/vendor/twig/twig/src/Cache/NullCache.php +34 -3
  310. src/lib/vendor/twig/twig/src/Compiler.php +280 -3
  311. src/lib/vendor/twig/twig/src/Environment.php +1639 -3
  312. src/lib/vendor/twig/twig/src/Error/Error.php +329 -3
  313. src/lib/vendor/twig/twig/src/Error/LoaderError.php +28 -4
  314. src/lib/vendor/twig/twig/src/Error/RuntimeError.php +19 -6
  315. src/lib/vendor/twig/twig/src/Error/SyntaxError.php +49 -3
  316. src/lib/vendor/twig/twig/src/ExpressionParser.php +757 -3
  317. src/lib/vendor/twig/twig/src/Extension/AbstractExtension.php +64 -3
  318. src/lib/vendor/twig/twig/src/Extension/CoreExtension.php +596 -4
icwp-plugin-controller.php CHANGED
@@ -17,7 +17,8 @@
17
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
18
  */
19
 
20
- use \FernleafSystems\Wordpress\Services\Services;
 
21
 
22
  class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
23
 
@@ -162,7 +163,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
162
 
163
  $sMinimumPhp = $this->getPluginSpec_Requirement( 'php' );
164
  if ( !empty( $sMinimumPhp ) ) {
165
- if ( version_compare( $this->loadDP()->getPhpVersion(), $sMinimumPhp, '<' ) ) {
166
  $aRequirementsMessages[] = sprintf( 'PHP does not meet minimum version. Your version: %s. Required Version: %s.', PHP_VERSION, $sMinimumPhp );
167
  $bMeetsRequirements = false;
168
  }
@@ -170,7 +171,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
170
 
171
  $sMinimumWp = $this->getPluginSpec_Requirement( 'wordpress' );
172
  if ( !empty( $sMinimumWp ) ) {
173
- $sWpVersion = $this->loadWp()->getVersion();
174
  if ( version_compare( $sWpVersion, $sMinimumWp, '<' ) ) {
175
  $aRequirementsMessages[] = sprintf( 'WordPress does not meet minimum version. Your version: %s. Required Version: %s.', $sWpVersion, $sMinimumWp );
176
  $bMeetsRequirements = false;
@@ -228,7 +229,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
228
  * @return bool
229
  */
230
  public function isThisPluginModuleRequest() {
231
- return strpos( $this->loadRequest()->query( 'page' ), $this->prefix() ) === 0;
232
  }
233
 
234
  /**
@@ -319,7 +320,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
319
  add_action( 'admin_menu', array( $this, 'onWpAdminMenu' ) );
320
  add_action( 'network_admin_menu', array( $this, 'onWpAdminMenu' ) );
321
 
322
- if ( $this->loadWp()->isAjax() ) {
323
  add_action( 'wp_ajax_'.$this->prefix(), array( $this, 'ajaxAction' ) );
324
  add_action( 'wp_ajax_nopriv_'.$this->prefix(), array( $this, 'ajaxAction' ) );
325
  }
@@ -348,6 +349,16 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
348
  $oNofics->setPrefix( $this->prefix() );
349
  add_filter( $this->prefix( 'ajaxAuthAction' ), array( $oNofics, 'handleAuthAjax' ) );
350
  }
 
 
 
 
 
 
 
 
 
 
351
  }
352
 
353
  /**
@@ -403,10 +414,10 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
403
  }
404
 
405
  public function ajaxAction() {
406
- $sNonceAction = $this->loadRequest()->request( 'exec' );
407
  check_ajax_referer( $sNonceAction, 'exec_nonce' );
408
 
409
- $sAction = $this->loadWpUsers()->isUserLoggedIn() ? 'ajaxAuthAction' : 'ajaxNonAuthAction';
410
  ob_start();
411
  $aResponseData = apply_filters( $this->prefix( $sAction ), array() );
412
  if ( empty( $aResponseData ) ) {
@@ -451,7 +462,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
451
 
452
  if ( $this->getPluginSpec_Menu( 'top_level' ) ) {
453
 
454
- $aLabels = $this->getPluginLabels();
455
  $sMenuTitle = empty( $aLabels[ 'MenuTitle' ] ) ? $this->getPluginSpec_Menu( 'title' ) : $aLabels[ 'MenuTitle' ];
456
  if ( is_null( $sMenuTitle ) ) {
457
  $sMenuTitle = $this->getHumanName();
@@ -679,7 +690,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
679
  * Displays a message in the plugins listing when a plugin has an update available.
680
  */
681
  public function onWpPluginUpdateMessage() {
682
- $sMessage = _wpsf__( 'Upgrade Now To Keep Your Security Up-To-Date With The Latest Features.' );
683
  if ( empty( $sMessage ) ) {
684
  $sMessage = '';
685
  }
@@ -724,14 +735,14 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
724
  && isset( $oPluginUpdateData->response[ $this->getPluginBaseFile() ] ) ) {
725
  // i.e. there's an update available
726
 
727
- $sNewVersion = $this->loadWpPlugins()->getUpdateNewVersion( $this->getPluginBaseFile() );
728
  if ( !empty( $sNewVersion ) ) {
729
  $oConOptions = $this->getPluginControllerOptions();
730
  if ( !isset( $oConOptions->update_first_detected ) || ( count( $oConOptions->update_first_detected ) > 3 ) ) {
731
  $oConOptions->update_first_detected = array();
732
  }
733
  if ( !isset( $oConOptions->update_first_detected[ $sNewVersion ] ) ) {
734
- $oConOptions->update_first_detected[ $sNewVersion ] = $this->loadRequest()->ts();
735
  }
736
 
737
  // a bit of cleanup to remove the old-style entries which would gather foreva-eva
@@ -755,7 +766,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
755
  */
756
  public function onWpAutoUpdate( $bDoAutoUpdate, $mItem ) {
757
  $oWp = $this->loadWp();
758
- $oWpPlugins = $this->loadWpPlugins();
759
 
760
  $sFile = $oWp->getFileFromAutomaticUpdateItem( $mItem );
761
 
@@ -791,10 +802,9 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
791
  case 'confidence' :
792
  $bDoAutoUpdate = false;
793
  $nAutoupdateDays = $this->getPluginSpec_Property( 'autoupdate_days' );
794
- $sNewVersion = $oWpPlugins->getUpdateNewVersion( $sFile );
795
  if ( !empty( $sNewVersion ) ) {
796
  $nFirstDetected = isset( $oConOptions->update_first_detected[ $sNewVersion ] ) ? $oConOptions->update_first_detected[ $sNewVersion ] : 0;
797
- $nTimeUpdateAvailable = $this->loadRequest()->ts() - $nFirstDetected;
798
  $bDoAutoUpdate = ( $nFirstDetected > 0 && ( $nTimeUpdateAvailable > DAY_IN_SECONDS*$nAutoupdateDays ) );
799
  }
800
  break;
@@ -814,7 +824,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
814
  * @return array
815
  */
816
  public function doPluginLabels( $aPlugins ) {
817
- $aLabelData = $this->getPluginLabels();
818
  if ( empty( $aLabelData ) ) {
819
  return $aPlugins;
820
  }
@@ -869,7 +879,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
869
  /**
870
  */
871
  protected function deleteFlags() {
872
- $oFS = $this->loadFS();
873
  if ( $oFS->exists( $this->getPath_Flags( 'rebuild' ) ) ) {
874
  $oFS->deleteFile( $this->getPath_Flags( 'rebuild' ) );
875
  }
@@ -909,7 +919,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
909
  */
910
  public function filter_hidePluginUpdatesFromUI( $oPlugins ) {
911
 
912
- if ( $this->loadWp()->isCron() ) {
913
  return $oPlugins;
914
  }
915
  if ( !apply_filters( $this->prefix( 'hide_plugin_updates' ), false ) ) {
@@ -943,8 +953,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
943
  do_action( $this->prefix( 'form_submit' ) );
944
 
945
  if ( $this->getIsPage_PluginAdmin() ) {
946
- $oWp = $this->loadWp();
947
- $oWp->doRedirect( $oWp->getUrl_CurrentAdminPage() );
948
  }
949
  return true;
950
  }
@@ -1072,7 +1081,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1072
  return false;
1073
  }
1074
 
1075
- $oWp = $this->loadWp();
1076
  if ( !$oWp->isMultisite() && is_admin() ) {
1077
  return true;
1078
  }
@@ -1140,7 +1149,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1140
  * @return string
1141
  */
1142
  public function getHumanName() {
1143
- $aLabels = $this->getPluginLabels();
1144
  return empty( $aLabels[ 'Name' ] ) ? $this->getPluginSpec_Property( 'human_name' ) : $aLabels[ 'Name' ];
1145
  }
1146
 
@@ -1155,27 +1164,27 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1155
  * @return bool
1156
  */
1157
  public function getIsPage_PluginAdmin() {
1158
- return ( strpos( $this->loadWp()->getCurrentWpAdminPage(), $this->getPluginPrefix() ) === 0 );
1159
  }
1160
 
1161
  /**
1162
  * @return bool
1163
  */
1164
  public function getIsPage_PluginMainDashboard() {
1165
- return ( $this->loadWp()->getCurrentWpAdminPage() == $this->getPluginPrefix() );
1166
  }
1167
 
1168
  /**
1169
  * @return bool
1170
  */
1171
  protected function isPluginFormSubmit() {
1172
- if ( $this->loadWp()->isAjax() || ( empty( $_POST ) && empty( $_GET ) ) ) {
1173
  return false;
1174
  }
1175
 
1176
- $aFormSubmitOptions = array( 'plugin_form_submit', 'icwp_link_action' );
1177
 
1178
- $oReq = $this->loadRequest();
1179
  foreach ( $aFormSubmitOptions as $sOption ) {
1180
  if ( !is_null( $oReq->request( $sOption, false ) ) ) {
1181
  return true;
@@ -1488,7 +1497,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1488
  protected function getPluginControllerOptions() {
1489
  if ( !isset( self::$oControllerOptions ) ) {
1490
 
1491
- self::$oControllerOptions = $this->loadWp()->getOption( $this->getPluginControllerOptionsKey() );
1492
  if ( !is_object( self::$oControllerOptions ) ) {
1493
  self::$oControllerOptions = new stdClass();
1494
  }
@@ -1564,7 +1573,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1564
  $oOptions = $this->getPluginControllerOptions();
1565
  if ( $this->sConfigOptionsHashWhenLoaded != md5( serialize( $oOptions ) ) ) {
1566
  add_filter( $this->prefix( 'bypass_is_plugin_admin' ), '__return_true' );
1567
- $this->loadWp()->updateOption( $this->getPluginControllerOptionsKey(), $oOptions );
1568
  remove_filter( $this->prefix( 'bypass_is_plugin_admin' ), '__return_true' );
1569
  }
1570
  }
@@ -1614,7 +1623,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1614
  */
1615
  public function deleteForceOffFile() {
1616
  if ( $this->getIfForceOffActive() ) {
1617
- $this->loadFS()->deleteFile( $this->getForceOffFilePath() );
1618
  $this->sForceOffFile = null;
1619
  clearstatcache();
1620
  }
@@ -1646,7 +1655,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1646
  */
1647
  public function getSessionId( $bSetIfNeeded = true ) {
1648
  if ( empty( self::$sSessionId ) ) {
1649
- self::$sSessionId = $this->loadRequest()->cookie( $this->getPluginPrefix(), '' );
1650
  if ( empty( self::$sSessionId ) && $bSetIfNeeded ) {
1651
  self::$sSessionId = md5( uniqid( $this->getPluginPrefix() ) );
1652
  $this->setSessionCookie();
@@ -1686,14 +1695,13 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1686
  /**
1687
  */
1688
  protected function setSessionCookie() {
1689
- $oWp = $this->loadWp();
1690
  $oReq = $this->loadRequest();
1691
  $oReq->setCookie(
1692
  $this->getPluginPrefix(),
1693
  $this->getSessionId(),
1694
  $oReq->ts() + DAY_IN_SECONDS*30,
1695
- $oWp->getCookiePath(),
1696
- $oWp->getCookieDomain(),
1697
  false
1698
  );
1699
  }
@@ -1791,7 +1799,7 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1791
  }
1792
 
1793
  if ( !empty( $aModProps[ 'min_php' ] )
1794
- && !$this->loadDP()->getPhpVersionIsAtLeast( $aModProps[ 'min_php' ] ) ) {
1795
  return null;
1796
  }
1797
 
@@ -1834,7 +1842,9 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1834
  $oMeta = null;
1835
  try {
1836
  if ( $oUser instanceof \WP_User ) {
 
1837
  $oMeta = \FernleafSystems\Wordpress\Plugin\Shield\Users\ShieldUserMeta::Load( $this->prefix(), $oUser->ID );
 
1838
  }
1839
  }
1840
  catch ( \Exception $oE ) {
@@ -1881,8 +1891,8 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1881
  */
1882
  public function wpPrivacyExport( $sEmail, $nPage = 1 ) {
1883
 
1884
- $bValid = $this->loadDP()->validEmail( $sEmail )
1885
- && ( $this->loadWpUsers()->getUserByEmail( $sEmail ) instanceof WP_User );
1886
 
1887
  return array(
1888
  'data' => $bValid ? apply_filters( $this->prefix( 'wpPrivacyExport' ), array(), $sEmail, $nPage ) : array(),
@@ -1897,8 +1907,8 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1897
  */
1898
  public function wpPrivacyErase( $sEmail, $nPage = 1 ) {
1899
 
1900
- $bValidUser = $this->loadDP()->validEmail( $sEmail )
1901
- && ( $this->loadWpUsers()->getUserByEmail( $sEmail ) instanceof WP_User );
1902
 
1903
  $aResult = array(
1904
  'items_removed' => $bValidUser,
@@ -1912,14 +1922,6 @@ class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
1912
  return $aResult;
1913
  }
1914
 
1915
- /**
1916
- * @deprecated 7.0.4
1917
- * @return array
1918
- */
1919
- public function getPluginLabels() {
1920
- return $this->getLabels();
1921
- }
1922
-
1923
  /**
1924
  * v5.4.1: Nasty looping bug in here where this function was called within the 'user_has_cap' filter
1925
  * so we removed the "current_user_can()" or any such sub-call within this function
17
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
18
  */
19
 
20
+ use FernleafSystems\Wordpress\Services\Services;
21
+ use FernleafSystems\Wordpress\Plugin\Shield;
22
 
23
  class ICWP_WPSF_Plugin_Controller extends ICWP_WPSF_Foundation {
24
 
163
 
164
  $sMinimumPhp = $this->getPluginSpec_Requirement( 'php' );
165
  if ( !empty( $sMinimumPhp ) ) {
166
+ if ( version_compare( Services::Data()->getPhpVersion(), $sMinimumPhp, '<' ) ) {
167
  $aRequirementsMessages[] = sprintf( 'PHP does not meet minimum version. Your version: %s. Required Version: %s.', PHP_VERSION, $sMinimumPhp );
168
  $bMeetsRequirements = false;
169
  }
171
 
172
  $sMinimumWp = $this->getPluginSpec_Requirement( 'wordpress' );
173
  if ( !empty( $sMinimumWp ) ) {
174
+ $sWpVersion = Services::WpGeneral()->getVersion( true );
175
  if ( version_compare( $sWpVersion, $sMinimumWp, '<' ) ) {
176
  $aRequirementsMessages[] = sprintf( 'WordPress does not meet minimum version. Your version: %s. Required Version: %s.', $sWpVersion, $sMinimumWp );
177
  $bMeetsRequirements = false;
229
  * @return bool
230
  */
231
  public function isThisPluginModuleRequest() {
232
+ return strpos( Services::Request()->query( 'page' ), $this->prefix() ) === 0;
233
  }
234
 
235
  /**
320
  add_action( 'admin_menu', array( $this, 'onWpAdminMenu' ) );
321
  add_action( 'network_admin_menu', array( $this, 'onWpAdminMenu' ) );
322
 
323
+ if ( Services::WpGeneral()->isAjax() ) {
324
  add_action( 'wp_ajax_'.$this->prefix(), array( $this, 'ajaxAction' ) );
325
  add_action( 'wp_ajax_nopriv_'.$this->prefix(), array( $this, 'ajaxAction' ) );
326
  }
349
  $oNofics->setPrefix( $this->prefix() );
350
  add_filter( $this->prefix( 'ajaxAuthAction' ), array( $oNofics, 'handleAuthAjax' ) );
351
  }
352
+
353
+ /**
354
+ * Support for WP-CLI and it marks the cli as complete plugin admin
355
+ */
356
+ add_filter( $this->prefix( 'bypass_is_plugin_admin' ), function ( $bByPass ) {
357
+ if ( Services::WpGeneral()->isWpCli() && $this->isPremiumActive() ) {
358
+ $bByPass = true;
359
+ }
360
+ return $bByPass;
361
+ }, PHP_INT_MAX );
362
  }
363
 
364
  /**
414
  }
415
 
416
  public function ajaxAction() {
417
+ $sNonceAction = Services::Request()->request( 'exec' );
418
  check_ajax_referer( $sNonceAction, 'exec_nonce' );
419
 
420
+ $sAction = Services::WpUsers()->isUserLoggedIn() ? 'ajaxAuthAction' : 'ajaxNonAuthAction';
421
  ob_start();
422
  $aResponseData = apply_filters( $this->prefix( $sAction ), array() );
423
  if ( empty( $aResponseData ) ) {
462
 
463
  if ( $this->getPluginSpec_Menu( 'top_level' ) ) {
464
 
465
+ $aLabels = $this->getLabels();
466
  $sMenuTitle = empty( $aLabels[ 'MenuTitle' ] ) ? $this->getPluginSpec_Menu( 'title' ) : $aLabels[ 'MenuTitle' ];
467
  if ( is_null( $sMenuTitle ) ) {
468
  $sMenuTitle = $this->getHumanName();
690
  * Displays a message in the plugins listing when a plugin has an update available.
691
  */
692
  public function onWpPluginUpdateMessage() {
693
+ $sMessage = _wpsf__( 'Update Now To Keep Your Security Current With The Latest Features.' );
694
  if ( empty( $sMessage ) ) {
695
  $sMessage = '';
696
  }
735
  && isset( $oPluginUpdateData->response[ $this->getPluginBaseFile() ] ) ) {
736
  // i.e. there's an update available
737
 
738
+ $sNewVersion = Services::WpPlugins()->getUpdateNewVersion( $this->getPluginBaseFile() );
739
  if ( !empty( $sNewVersion ) ) {
740
  $oConOptions = $this->getPluginControllerOptions();
741
  if ( !isset( $oConOptions->update_first_detected ) || ( count( $oConOptions->update_first_detected ) > 3 ) ) {
742
  $oConOptions->update_first_detected = array();
743
  }
744
  if ( !isset( $oConOptions->update_first_detected[ $sNewVersion ] ) ) {
745
+ $oConOptions->update_first_detected[ $sNewVersion ] = Services::Request()->ts();
746
  }
747
 
748
  // a bit of cleanup to remove the old-style entries which would gather foreva-eva
766
  */
767
  public function onWpAutoUpdate( $bDoAutoUpdate, $mItem ) {
768
  $oWp = $this->loadWp();
769
+ $oWpPlugins = Services::WpPlugins();
770
 
771
  $sFile = $oWp->getFileFromAutomaticUpdateItem( $mItem );
772
 
802
  case 'confidence' :
803
  $bDoAutoUpdate = false;
804
  $nAutoupdateDays = $this->getPluginSpec_Property( 'autoupdate_days' );
 
805
  if ( !empty( $sNewVersion ) ) {
806
  $nFirstDetected = isset( $oConOptions->update_first_detected[ $sNewVersion ] ) ? $oConOptions->update_first_detected[ $sNewVersion ] : 0;
807
+ $nTimeUpdateAvailable = Services::Request()->ts() - $nFirstDetected;
808
  $bDoAutoUpdate = ( $nFirstDetected > 0 && ( $nTimeUpdateAvailable > DAY_IN_SECONDS*$nAutoupdateDays ) );
809
  }
810
  break;
824
  * @return array
825
  */
826
  public function doPluginLabels( $aPlugins ) {
827
+ $aLabelData = $this->getLabels();
828
  if ( empty( $aLabelData ) ) {
829
  return $aPlugins;
830
  }
879
  /**
880
  */
881
  protected function deleteFlags() {
882
+ $oFS = Services::WpFs();
883
  if ( $oFS->exists( $this->getPath_Flags( 'rebuild' ) ) ) {
884
  $oFS->deleteFile( $this->getPath_Flags( 'rebuild' ) );
885
  }
919
  */
920
  public function filter_hidePluginUpdatesFromUI( $oPlugins ) {
921
 
922
+ if ( Services::WpGeneral()->isCron() ) {
923
  return $oPlugins;
924
  }
925
  if ( !apply_filters( $this->prefix( 'hide_plugin_updates' ), false ) ) {
953
  do_action( $this->prefix( 'form_submit' ) );
954
 
955
  if ( $this->getIsPage_PluginAdmin() ) {
956
+ Services::Response()->redirect( Services::WpGeneral()->getUrl_CurrentAdminPage() );
 
957
  }
958
  return true;
959
  }
1081
  return false;
1082
  }
1083
 
1084
+ $oWp = Services::WpGeneral();
1085
  if ( !$oWp->isMultisite() && is_admin() ) {
1086
  return true;
1087
  }
1149
  * @return string
1150
  */
1151
  public function getHumanName() {
1152
+ $aLabels = $this->getLabels();
1153
  return empty( $aLabels[ 'Name' ] ) ? $this->getPluginSpec_Property( 'human_name' ) : $aLabels[ 'Name' ];
1154
  }
1155
 
1164
  * @return bool
1165
  */
1166
  public function getIsPage_PluginAdmin() {
1167
+ return ( strpos( Services::WpGeneral()->getCurrentWpAdminPage(), $this->getPluginPrefix() ) === 0 );
1168
  }
1169
 
1170
  /**
1171
  * @return bool
1172
  */
1173
  public function getIsPage_PluginMainDashboard() {
1174
+ return ( Services::WpGeneral()->getCurrentWpAdminPage() == $this->getPluginPrefix() );
1175
  }
1176
 
1177
  /**
1178
  * @return bool
1179
  */
1180
  protected function isPluginFormSubmit() {
1181
+ if ( Services::WpGeneral()->isAjax() || ( empty( $_POST ) && empty( $_GET ) ) ) {
1182
  return false;
1183
  }
1184
 
1185
+ $aFormSubmitOptions = [ 'plugin_form_submit', 'icwp_link_action' ];
1186
 
1187
+ $oReq = Services::Request();
1188
  foreach ( $aFormSubmitOptions as $sOption ) {
1189
  if ( !is_null( $oReq->request( $sOption, false ) ) ) {
1190
  return true;
1497
  protected function getPluginControllerOptions() {
1498
  if ( !isset( self::$oControllerOptions ) ) {
1499
 
1500
+ self::$oControllerOptions = Services::WpGeneral()->getOption( $this->getPluginControllerOptionsKey() );
1501
  if ( !is_object( self::$oControllerOptions ) ) {
1502
  self::$oControllerOptions = new stdClass();
1503
  }
1573
  $oOptions = $this->getPluginControllerOptions();
1574
  if ( $this->sConfigOptionsHashWhenLoaded != md5( serialize( $oOptions ) ) ) {
1575
  add_filter( $this->prefix( 'bypass_is_plugin_admin' ), '__return_true' );
1576
+ Services::WpGeneral()->updateOption( $this->getPluginControllerOptionsKey(), $oOptions );
1577
  remove_filter( $this->prefix( 'bypass_is_plugin_admin' ), '__return_true' );
1578
  }
1579
  }
1623
  */
1624
  public function deleteForceOffFile() {
1625
  if ( $this->getIfForceOffActive() ) {
1626
+ Services::WpFs()->deleteFile( $this->getForceOffFilePath() );
1627
  $this->sForceOffFile = null;
1628
  clearstatcache();
1629
  }
1655
  */
1656
  public function getSessionId( $bSetIfNeeded = true ) {
1657
  if ( empty( self::$sSessionId ) ) {
1658
+ self::$sSessionId = Services::Request()->cookie( $this->getPluginPrefix(), '' );
1659
  if ( empty( self::$sSessionId ) && $bSetIfNeeded ) {
1660
  self::$sSessionId = md5( uniqid( $this->getPluginPrefix() ) );
1661
  $this->setSessionCookie();
1695
  /**
1696
  */
1697
  protected function setSessionCookie() {
 
1698
  $oReq = $this->loadRequest();
1699
  $oReq->setCookie(
1700
  $this->getPluginPrefix(),
1701
  $this->getSessionId(),
1702
  $oReq->ts() + DAY_IN_SECONDS*30,
1703
+ Services::WpGeneral()->getCookiePath(),
1704
+ Services::WpGeneral()->getCookieDomain(),
1705
  false
1706
  );
1707
  }
1799
  }
1800
 
1801
  if ( !empty( $aModProps[ 'min_php' ] )
1802
+ && !Services::Data()->getPhpVersionIsAtLeast( $aModProps[ 'min_php' ] ) ) {
1803
  return null;
1804
  }
1805
 
1842
  $oMeta = null;
1843
  try {
1844
  if ( $oUser instanceof \WP_User ) {
1845
+ /** @var \FernleafSystems\Wordpress\Plugin\Shield\Users\ShieldUserMeta $oMeta */
1846
  $oMeta = \FernleafSystems\Wordpress\Plugin\Shield\Users\ShieldUserMeta::Load( $this->prefix(), $oUser->ID );
1847
+ $oMeta->setPasswordStartedAt( $oUser->user_pass );
1848
  }
1849
  }
1850
  catch ( \Exception $oE ) {
1891
  */
1892
  public function wpPrivacyExport( $sEmail, $nPage = 1 ) {
1893
 
1894
+ $bValid = Services::Data()->validEmail( $sEmail )
1895
+ && ( Services::WpUsers()->getUserByEmail( $sEmail ) instanceof WP_User );
1896
 
1897
  return array(
1898
  'data' => $bValid ? apply_filters( $this->prefix( 'wpPrivacyExport' ), array(), $sEmail, $nPage ) : array(),
1907
  */
1908
  public function wpPrivacyErase( $sEmail, $nPage = 1 ) {
1909
 
1910
+ $bValidUser = Services::Data()->validEmail( $sEmail )
1911
+ && ( Services::WpUsers()->getUserByEmail( $sEmail ) instanceof WP_User );
1912
 
1913
  $aResult = array(
1914
  'items_removed' => $bValidUser,
1922
  return $aResult;
1923
  }
1924
 
 
 
 
 
 
 
 
 
1925
  /**
1926
  * v5.4.1: Nasty looping bug in here where this function was called within the 'user_has_cap' filter
1927
  * so we removed the "current_user_can()" or any such sub-call within this function
icwp-wpsf.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Shield Security
4
  * Plugin URI: https://icwp.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
- * Version: 7.1.2
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages/
9
  * Author: One Dollar Plugin
3
  * Plugin Name: Shield Security
4
  * Plugin URI: https://icwp.io/2f
5
  * Description: Powerful, Easy-To-Use #1 Rated WordPress Security System
6
+ * Version: 7.2.3
7
  * Text Domain: wp-simple-firewall
8
  * Domain Path: /languages/
9
  * Author: One Dollar Plugin
plugin-spec.php CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "properties": {
3
- "version": "7.1.2",
4
- "release_timestamp": 1551287600,
5
  "slug_parent": "icwp",
6
  "slug_plugin": "wpsf",
7
  "human_name": "Shield",
1
  {
2
  "properties": {
3
+ "version": "7.2.3",
4
+ "release_timestamp": 1553515200,
5
  "slug_parent": "icwp",
6
  "slug_plugin": "wpsf",
7
  "human_name": "Shield",
readme.txt CHANGED
@@ -1,26 +1,36 @@
1
- === Shield Security for WordPress ===
2
  Contributors: onedollarplugin, paultgoodchild
3
  Donate link: https://icwp.io/bw
4
  License: GPLv3
5
  License URI: http://www.gnu.org/licenses/gpl.html
6
- Tags: security, all in one, scan, firewall, two factor authentication, spam, wordfence, cerber, ithemes
7
  Requires at least: 3.5.0
8
  Requires PHP: 5.4.0
9
  Recommended PHP: 7.0
10
  Tested up to: 5.1
11
- Stable tag: 7.1.2
12
 
13
- Complete All-In-One Protection for your WordPress sites, that makes Security Easy for Everyone - it doesn't have to be hard anymore.
14
 
15
  == Description ==
16
 
 
 
 
 
 
 
 
 
 
 
17
  ### Powerful Security for WordPress *doesn't* need to be *hard*
18
 
19
- There's no good reason for WordPress security plugins to be so complicated. It doesn't have to be that way.
20
 
21
  Shield is the easiest security plugin to setup - you simply activate it. Then a beautiful, step-by-step wizard will walk you through the basic configuration.
22
 
23
- And you can dig deeper, any time you're ready.
24
 
25
  #### Trust: Shield Does Exactly What It Says It Will Do
26
 
@@ -352,15 +362,29 @@ You will always be able to use Shield Security and its free features in-full.
352
 
353
  [Go Pro for just $1/month](https://icwp.io/aa).
354
 
355
- = 7.1.2 - Current Release =
356
- *Released: 27th February, 2019* - [Release Notes](https://icwp.io/ek)
357
 
358
- * **(v.2)** IMPROVED: Firewall email notification content now better reflect the information in the audit trail.
359
- * **(v.2)** FIX: Firewall email notification was breaking in some instances.
 
 
 
 
 
 
 
 
 
 
 
 
360
 
361
  = 7.1 - Series =
362
  *Released: 21st February, 2019* - [Release Notes](https://icwp.io/ek)
363
 
 
 
364
  * **(v.1)** FIX: IP retrieval.
365
  * **(v.0)** NEW: Moved Import/Export UI from Wizard to main Shield Dashboard.
366
  * **(v.0)** NEW: [**PRO**] Option to import/export settings using file downloads/uploads
1
+ === Shield: Security, Scanning & Protection For All ===
2
  Contributors: onedollarplugin, paultgoodchild
3
  Donate link: https://icwp.io/bw
4
  License: GPLv3
5
  License URI: http://www.gnu.org/licenses/gpl.html
6
+ Tags: scan, firewall, two factor authentication, login protection, security
7
  Requires at least: 3.5.0
8
  Requires PHP: 5.4.0
9
  Recommended PHP: 7.0
10
  Tested up to: 5.1
11
+ Stable tag: 7.2.3
12
 
13
+ All-In-One protection against hackers and bot attacks. Easy to use Scanners, 2-Factor Authentication, login protection, auto IP blocker, and so much more...
14
 
15
  == Description ==
16
 
17
+ ### The highest rated 5* Security Plugin for WordPress
18
+
19
+ Shield has the highest average 5* rating for any WordPress security plugin (2019/03). [See what people are saying here](https://wordpress.org/support/plugin/wp-simple-firewall/reviews/?filter=5)..
20
+
21
+ #### Our Mission: No Site Left Behind.
22
+
23
+ We're driven by our mission to offer protection to **every single site**. We're not here to scare you, but help you start, *right now*, protecting what's important to you and your business.
24
+
25
+ Getting started is easy, and we'll help you through every step. All our security options are fully documented so you can understand and stay informed as you progress.
26
+
27
  ### Powerful Security for WordPress *doesn't* need to be *hard*
28
 
29
+ There's no reason for security plugins to be complicated. It just doesn't have to be that way.
30
 
31
  Shield is the easiest security plugin to setup - you simply activate it. Then a beautiful, step-by-step wizard will walk you through the basic configuration.
32
 
33
+ And you can dig deeper, when you're ready.
34
 
35
  #### Trust: Shield Does Exactly What It Says It Will Do
36
 
362
 
363
  [Go Pro for just $1/month](https://icwp.io/aa).
364
 
365
+ = 7.2.3 - Current Release =
366
+ *Released: 25th March, 2019* - [Release Notes](https://icwp.io/ep)
367
 
368
+ * **(v.3)** FIX: Unable to turn off the Abandoned Plugin scanner.
369
+ * **(v.3)** FIX: Fix bug with some DNS lookup failures for some ISPs.
370
+ * **(v.3)** FIX: Fix display notice for 'disallow file editing' setting when IP is whitelisted.
371
+
372
+ = 7.2 - Series =
373
+ *Released: 7th March, 2019* - [Release Notes](https://icwp.io/ep)
374
+
375
+ * **(v.2)** SKIPPED: with error.
376
+ * **(v.1)** NEW: Provisional support for WP-CLI - no longer blocks Security Admin protected operations
377
+ * **(v.1)** FIX: Fix PHP warning notice on login page.
378
+ * **(v.1)** FIX: Unrecognised file scanning not operating as expected on Windows hosts.
379
+ * **(v.0)** NEW: [Scanner to detect and alert](https://icwp.io/eq) to presence of abandoned plugins.
380
+ * **(v.0)** FIX: Fix bug with Security Admin passwords.
381
+ * **(v.0)** FIX: Fix bug with vulnerability scanner not correctly comparing versions.
382
 
383
  = 7.1 - Series =
384
  *Released: 21st February, 2019* - [Release Notes](https://icwp.io/ek)
385
 
386
+ * **(v.2)** IMPROVED: Firewall email notification content now better reflect the information in the audit trail.
387
+ * **(v.2)** FIX: Firewall email notification was breaking in some instances.
388
  * **(v.1)** FIX: IP retrieval.
389
  * **(v.0)** NEW: Moved Import/Export UI from Wizard to main Shield Dashboard.
390
  * **(v.0)** NEW: [**PRO**] Option to import/export settings using file downloads/uploads
resources/css/plugin.css CHANGED
@@ -1102,12 +1102,15 @@ table.scan-table.wp-list-table button.toggle-row {
1102
  margin-top: 25px;
1103
  }
1104
  #ScanResultsPills nav > a.nav-link {
1105
- color: #0c7905;
1106
  height: 72px;
 
1107
  }
1108
  #ScanResultsPills nav > a.nav-link.active {
1109
- color: #ffffff;
1110
- background-color: #0c7905;
 
 
1111
  }
1112
  #ScanResultsPills .card.card-scan_results {
1113
  margin-top: 0;
1102
  margin-top: 25px;
1103
  }
1104
  #ScanResultsPills nav > a.nav-link {
1105
+ color: #666666;
1106
  height: 72px;
1107
+ margin-bottom: 15px;
1108
  }
1109
  #ScanResultsPills nav > a.nav-link.active {
1110
+ background-color: transparent;
1111
+ color: #333333;
1112
+ font-weight: bolder;
1113
+ font-size: 14px;
1114
  }
1115
  #ScanResultsPills .card.card-scan_results {
1116
  margin-top: 0;
src/common/icwp-data.php CHANGED
@@ -581,15 +581,6 @@ class ICWP_WPSF_DataProcessor extends ICWP_WPSF_Foundation {
581
  return $this->loadRequest()->getScriptName();
582
  }
583
 
584
- /**
585
- * @deprecated
586
- * @param string $sRequestedUriPath
587
- * @param string $sHostName - you can also send a full and valid URL
588
- */
589
- public function doSendApache404( $sRequestedUriPath = '', $sHostName = '' ) {
590
- return $this->loadRequest()->sendResponseApache404( $sRequestedUriPath, $sHostName );
591
- }
592
-
593
  /**
594
  * @deprecated
595
  * @param $sKey
581
  return $this->loadRequest()->getScriptName();
582
  }
583
 
 
 
 
 
 
 
 
 
 
584
  /**
585
  * @deprecated
586
  * @param $sKey
src/common/icwp-edd.php CHANGED
@@ -101,7 +101,7 @@ class ICWP_WPSF_Edd {
101
  private function commonLicenseAction( $sAction, $sStoreUrl, $sKey, $sItemId ) {
102
  $oWp = Services::WpGeneral();
103
  $aLicenseLookupParams = array(
104
- 'timeout' => 30,
105
  'body' => array_merge(
106
  array(
107
  'edd_action' => $sAction,
101
  private function commonLicenseAction( $sAction, $sStoreUrl, $sKey, $sItemId ) {
102
  $oWp = Services::WpGeneral();
103
  $aLicenseLookupParams = array(
104
+ 'timeout' => 60,
105
  'body' => array_merge(
106
  array(
107
  'edd_action' => $sAction,
src/common/icwp-ip.php CHANGED
@@ -271,7 +271,7 @@ class ICWP_WPSF_Ip extends ICWP_WPSF_Foundation {
271
  * @return string
272
  */
273
  public function determineSourceFromIp( $sVisitorIp ) {
274
- $oReq = $this->loadRequest();
275
 
276
  $sBestSource = null;
277
  foreach ( $this->getIpSourceOptions() as $sSource ) {
@@ -313,7 +313,7 @@ class ICWP_WPSF_Ip extends ICWP_WPSF_Foundation {
313
 
314
  $sIpToReturn = false;
315
  $sSource = false;
316
- $oReq = $this->loadRequest();
317
  foreach ( $this->getIpSourceOptions() as $sMaybeSource ) {
318
 
319
  $sIpToTest = $oReq->server( $sMaybeSource );
271
  * @return string
272
  */
273
  public function determineSourceFromIp( $sVisitorIp ) {
274
+ $oReq = Services::Request();
275
 
276
  $sBestSource = null;
277
  foreach ( $this->getIpSourceOptions() as $sSource ) {
313
 
314
  $sIpToReturn = false;
315
  $sSource = false;
316
+ $oReq = Services::Request();
317
  foreach ( $this->getIpSourceOptions() as $sMaybeSource ) {
318
 
319
  $sIpToTest = $oReq->server( $sMaybeSource );
src/common/icwp-optionsvo.php CHANGED
@@ -636,7 +636,16 @@ class ICWP_WPSF_OptionsVO extends ICWP_WPSF_Foundation {
636
  * @return bool
637
  */
638
  public function isModuleRunIfWhitelisted() {
639
- return (bool)$this->getFeatureProperty( 'run_if_whitelisted' );
 
 
 
 
 
 
 
 
 
640
  }
641
 
642
  /**
636
  * @return bool
637
  */
638
  public function isModuleRunIfWhitelisted() {
639
+ $bState = $this->getFeatureProperty( 'run_if_whitelisted' );
640
+ return is_null( $bState ) ? true : (bool)$bState;
641
+ }
642
+
643
+ /**
644
+ * @return bool
645
+ */
646
+ public function isModuleRunUnderWpCli() {
647
+ $bState = $this->getFeatureProperty( 'run_if_wpcli' );
648
+ return is_null( $bState ) ? true : (bool)$bState;
649
  }
650
 
651
  /**
src/common/icwp-serviceproviders.php CHANGED
@@ -456,7 +456,7 @@ class ICWP_WPSF_ServiceProviders extends ICWP_WPSF_Foundation {
456
  if ( !$bCheckIpHost ) {
457
  $aBotUserAgents = array_map(
458
  function ( $sAgent ) {
459
- preg_quote( $sAgent, '#' );
460
  },
461
  $aBotUserAgents
462
  );
456
  if ( !$bCheckIpHost ) {
457
  $aBotUserAgents = array_map(
458
  function ( $sAgent ) {
459
+ return preg_quote( $sAgent, '#' );
460
  },
461
  $aBotUserAgents
462
  );
src/common/icwp-wpfunctions.php CHANGED
@@ -532,7 +532,7 @@ class ICWP_WPSF_WpFunctions extends ICWP_WPSF_Foundation {
532
  * @param string
533
  * @return string
534
  */
535
- public function getIsPage_Updates() {
536
  return $this->isCurrentPage( 'update.php' );
537
  }
538
 
532
  * @param string
533
  * @return string
534
  */
535
+ public function isPage_Updates() {
536
  return $this->isCurrentPage( 'update.php' );
537
  }
538
 
src/config/feature-admin_access_restriction.php CHANGED
@@ -12,6 +12,7 @@
12
  "premium": false,
13
  "run_if_whitelisted": false,
14
  "run_if_verified_bot": true,
 
15
  "order": 20
16
  },
17
  "admin_notices": {
12
  "premium": false,
13
  "run_if_whitelisted": false,
14
  "run_if_verified_bot": true,
15
+ "run_if_wpcli": false,
16
  "order": 20
17
  },
18
  "admin_notices": {
src/config/feature-audit_trail.php CHANGED
@@ -2,7 +2,7 @@
2
  "slug": "audit_trail",
3
  "properties": {
4
  "slug": "audit_trail",
5
- "name": "Audit Trail",
6
  "show_module_menu_item": false,
7
  "show_module_options": true,
8
  "storage_key": "audit_trail",
@@ -12,6 +12,7 @@
12
  "premium": false,
13
  "run_if_whitelisted": true,
14
  "run_if_verified_bot": false,
 
15
  "order": 110
16
  },
17
  "sections": [
@@ -34,6 +35,16 @@
34
  "Recommendation - These settings are dependent on your requirements."
35
  ]
36
  },
 
 
 
 
 
 
 
 
 
 
37
  {
38
  "slug": "section_enable_plugin_feature_audit_trail",
39
  "title": "Enable Module: Audit Trail",
@@ -161,6 +172,62 @@
161
  "name": "Shield",
162
  "summary": "Enable Audit Context - Shield",
163
  "description": "When this context is enabled, the audit trail will track activity relating to: Shield"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  }
165
  ],
166
  "definitions": {
@@ -179,6 +246,14 @@
179
  "meta",
180
  "created_at",
181
  "deleted_at"
 
 
 
 
 
 
 
 
182
  ]
183
  }
184
  }
2
  "slug": "audit_trail",
3
  "properties": {
4
  "slug": "audit_trail",
5
+ "name": "Auditing",
6
  "show_module_menu_item": false,
7
  "show_module_options": true,
8
  "storage_key": "audit_trail",
12
  "premium": false,
13
  "run_if_whitelisted": true,
14
  "run_if_verified_bot": false,
15
+ "run_if_wpcli": true,
16
  "order": 110
17
  },
18
  "sections": [
35
  "Recommendation - These settings are dependent on your requirements."
36
  ]
37
  },
38
+ {
39
+ "slug": "section_change_tracking",
40
+ "hidden": true,
41
+ "title": "Change Tracking",
42
+ "title_short": "Change Tracking",
43
+ "summary": [
44
+ "Purpose - Track significant changes to your site.",
45
+ "Recommendation - Keep this Reporting feature turned on."
46
+ ]
47
+ },
48
  {
49
  "slug": "section_enable_plugin_feature_audit_trail",
50
  "title": "Enable Module: Audit Trail",
172
  "name": "Shield",
173
  "summary": "Enable Audit Context - Shield",
174
  "description": "When this context is enabled, the audit trail will track activity relating to: Shield"
175
+ },
176
+ {
177
+ "key": "enable_change_tracking",
178
+ "section": "section_change_tracking",
179
+ "default": "disabled",
180
+ "type": "select",
181
+ "value_options": [
182
+ {
183
+ "value_key": "disabled",
184
+ "text": "Disabled"
185
+ },
186
+ {
187
+ "value_key": "enabled",
188
+ "text": "Enabled"
189
+ },
190
+ {
191
+ "value_key": "enabled_with_email",
192
+ "text": "Enabled With Email Reports"
193
+ }
194
+ ],
195
+ "link_info": "",
196
+ "link_blog": "",
197
+ "name": "Enable Change Tracking",
198
+ "summary": "Track Major Changes To Your Site",
199
+ "description": "Tracking major changes to your site will help you monitor and catch malicious damage."
200
+ },
201
+ {
202
+ "key": "ct_snapshots_per_week",
203
+ "section": "section_change_tracking",
204
+ "type": "integer",
205
+ "default": 7,
206
+ "min": 1,
207
+ "link_info": "",
208
+ "link_blog": "",
209
+ "name": "Snapshot Per Week",
210
+ "summary": "Number Of Snapshots To Take Per Week",
211
+ "description": "The number of snapshots to take per week. For daily snapshots, select 7."
212
+ },
213
+ {
214
+ "key": "ct_max_snapshots",
215
+ "section": "section_change_tracking",
216
+ "type": "integer",
217
+ "default": 28,
218
+ "min": 1,
219
+ "link_info": "",
220
+ "link_blog": "",
221
+ "name": "Snapshot Per Week",
222
+ "summary": "Number Of Snapshots To Take Per Week",
223
+ "description": "The number of snapshots to take per week. For daily snapshots, select 7."
224
+ },
225
+ {
226
+ "key": "ct_last_snapshot_at",
227
+ "section": "section_non_ui",
228
+ "transferable": false,
229
+ "type": "integer",
230
+ "default": 0
231
  }
232
  ],
233
  "definitions": {
246
  "meta",
247
  "created_at",
248
  "deleted_at"
249
+ ],
250
+ "table_name_changetracking": "changetracking",
251
+ "table_columns_changetracking": [
252
+ "id",
253
+ "data",
254
+ "meta",
255
+ "created_at",
256
+ "deleted_at"
257
  ]
258
  }
259
  }
src/config/feature-autoupdates.php CHANGED
@@ -12,6 +12,7 @@
12
  "premium": false,
13
  "run_if_whitelisted": true,
14
  "run_if_verified_bot": true,
 
15
  "order": 60
16
  },
17
  "sections": [
@@ -213,6 +214,7 @@
213
  "key": "delay_tracking",
214
  "section": "section_non_ui",
215
  "transferable": false,
 
216
  "type": "array",
217
  "default": []
218
  },
12
  "premium": false,
13
  "run_if_whitelisted": true,
14
  "run_if_verified_bot": true,
15
+ "run_if_wpcli": true,
16
  "order": 60
17
  },
18
  "sections": [
214
  "key": "delay_tracking",
215
  "section": "section_non_ui",
216
  "transferable": false,
217
+ "sensitive": true,
218
  "type": "array",
219
  "default": []
220
  },
src/config/feature-comments_filter.php CHANGED
@@ -13,6 +13,7 @@
13
  "premium": false,
14
  "run_if_whitelisted": false,
15
  "run_if_verified_bot": false,
 
16
  "order": 50
17
  },
18
  "admin_notices": {
13
  "premium": false,
14
  "run_if_whitelisted": false,
15
  "run_if_verified_bot": false,
16
+ "run_if_wpcli": false,
17
  "order": 50
18
  },
19
  "admin_notices": {
src/config/feature-email.php CHANGED
@@ -9,7 +9,8 @@
9
  "show_central": false,
10
  "premium": false,
11
  "access_restricted": true,
12
- "run_if_whitelisted": true
 
13
  },
14
  "sections": [
15
  {
9
  "show_central": false,
10
  "premium": false,
11
  "access_restricted": true,
12
+ "run_if_whitelisted": true,
13
+ "run_if_wpcli": true
14
  },
15
  "sections": [
16
  {
src/config/feature-firewall.php CHANGED
@@ -12,6 +12,7 @@
12
  "premium": false,
13
  "run_if_whitelisted": false,
14
  "run_if_verified_bot": false,
 
15
  "order": 30
16
  },
17
  "sections": [
@@ -295,6 +296,8 @@
295
  "wp_http_referer",
296
  "_wp_http_referer",
297
  "_wp_original_http_referer",
 
 
298
  "pwd",
299
  "url",
300
  "referredby",
12
  "premium": false,
13
  "run_if_whitelisted": false,
14
  "run_if_verified_bot": false,
15
+ "run_if_wpcli": false,
16
  "order": 30
17
  },
18
  "sections": [
296
  "wp_http_referer",
297
  "_wp_http_referer",
298
  "_wp_original_http_referer",
299
+ "pass1",
300
+ "pass1-text",
301
  "pwd",
302
  "url",
303
  "referredby",
src/config/feature-hack_protect.php CHANGED
@@ -12,7 +12,8 @@
12
  "premium": false,
13
  "order": 70,
14
  "run_if_whitelisted": true,
15
- "run_if_verified_bot": true
 
16
  },
17
  "sections": [
18
  {
@@ -42,11 +43,17 @@
42
  "Recommendation - Keep the Unrecognised Files Scanner feature turned on."
43
  ]
44
  },
 
 
 
 
 
 
 
 
 
45
  {
46
  "slug": "section_pluginthemes_guard",
47
- "reqs": {
48
- "php_min": "5.4"
49
- },
50
  "help_video": {
51
  "provider": "vimeo",
52
  "embed_url": "https://player.vimeo.com/video/256755089?color=3fde23&byline=0",
@@ -68,16 +75,6 @@
68
  "Recommendation - Ensure this is turned on and you will always know if any of your assets have known security vulnerabilities."
69
  ]
70
  },
71
- {
72
- "slug": "section_scan_apc",
73
- "hidden": true,
74
- "title": "Abandoned Plugin Check",
75
- "title_short": "Abandoned Plugin Check",
76
- "summary": [
77
- "Purpose - Regularly scan your WordPress plugins and themes for plugins that have been abandoned.",
78
- "Recommendation - Ensure this is turned on and you will always know if any of your assets have known security vulnerabilities."
79
- ]
80
- },
81
  {
82
  "slug": "section_integrity_checking",
83
  "title": "Integrity Checks",
@@ -179,7 +176,6 @@
179
  {
180
  "key": "enabled_scan_apc",
181
  "section": "section_scan_apc",
182
- "premium": true,
183
  "default": "enabled_email",
184
  "type": "select",
185
  "value_options": [
@@ -196,23 +192,12 @@
196
  "text": "Enabled - No Email Notification"
197
  }
198
  ],
199
- "link_info": "",
200
- "link_blog": "",
201
  "name": "Abandoned Plugin Scanner",
202
  "summary": "Enable The Abandoned Plugin Scanner",
203
  "description": "Scan your WordPress.org assets for whether they've been abandoned."
204
  },
205
- {
206
- "key": "display_apc",
207
- "section": "section_scan_apc",
208
- "type": "checkbox",
209
- "default": "Y",
210
- "link_info": "",
211
- "link_blog": "",
212
- "name": "Highlight Plugins",
213
- "summary": "Highlight Abandoned Plugins",
214
- "description": "Abandoned plugins will be highlighted on the main plugins page."
215
- },
216
  {
217
  "key": "enable_core_file_integrity_scan",
218
  "section": "section_core_file_integrity_scan",
@@ -486,6 +471,13 @@
486
  "type": "integer",
487
  "default": 0
488
  },
 
 
 
 
 
 
 
489
  {
490
  "key": "insights_last_scan_wcf_at",
491
  "section": "section_non_ui",
@@ -507,6 +499,13 @@
507
  "type": "integer",
508
  "default": 0
509
  },
 
 
 
 
 
 
 
510
  {
511
  "key": "next_scan_ufc_at",
512
  "section": "section_non_ui",
12
  "premium": false,
13
  "order": 70,
14
  "run_if_whitelisted": true,
15
+ "run_if_verified_bot": true,
16
+ "run_if_wpcli": false
17
  },
18
  "sections": [
19
  {
43
  "Recommendation - Keep the Unrecognised Files Scanner feature turned on."
44
  ]
45
  },
46
+ {
47
+ "slug": "section_scan_apc",
48
+ "title": "Abandoned Plugin Check",
49
+ "title_short": "Abandoned Plugin Check",
50
+ "summary": [
51
+ "Purpose - Regularly scan your WordPress plugins and themes for plugins that have been abandoned.",
52
+ "Recommendation - Ensure this is turned on and you will always know if any of your assets have known security vulnerabilities."
53
+ ]
54
+ },
55
  {
56
  "slug": "section_pluginthemes_guard",
 
 
 
57
  "help_video": {
58
  "provider": "vimeo",
59
  "embed_url": "https://player.vimeo.com/video/256755089?color=3fde23&byline=0",
75
  "Recommendation - Ensure this is turned on and you will always know if any of your assets have known security vulnerabilities."
76
  ]
77
  },
 
 
 
 
 
 
 
 
 
 
78
  {
79
  "slug": "section_integrity_checking",
80
  "title": "Integrity Checks",
176
  {
177
  "key": "enabled_scan_apc",
178
  "section": "section_scan_apc",
 
179
  "default": "enabled_email",
180
  "type": "select",
181
  "value_options": [
192
  "text": "Enabled - No Email Notification"
193
  }
194
  ],
195
+ "link_info": "https://icwp.io/ew",
196
+ "link_blog": "https://icwp.io/eo",
197
  "name": "Abandoned Plugin Scanner",
198
  "summary": "Enable The Abandoned Plugin Scanner",
199
  "description": "Scan your WordPress.org assets for whether they've been abandoned."
200
  },
 
 
 
 
 
 
 
 
 
 
 
201
  {
202
  "key": "enable_core_file_integrity_scan",
203
  "section": "section_core_file_integrity_scan",
471
  "type": "integer",
472
  "default": 0
473
  },
474
+ {
475
+ "key": "insights_last_scan_apc_at",
476
+ "section": "section_non_ui",
477
+ "transferable": false,
478
+ "type": "integer",
479
+ "default": 0
480
+ },
481
  {
482
  "key": "insights_last_scan_wcf_at",
483
  "section": "section_non_ui",
499
  "type": "integer",
500
  "default": 0
501
  },
502
+ {
503
+ "key": "next_scan_apc_at",
504
+ "section": "section_non_ui",
505
+ "transferable": false,
506
+ "type": "integer",
507
+ "default": 0
508
+ },
509
  {
510
  "key": "next_scan_ufc_at",
511
  "section": "section_non_ui",
src/config/feature-headers.php CHANGED
@@ -12,6 +12,7 @@
12
  "premium": false,
13
  "run_if_whitelisted": false,
14
  "run_if_verified_bot": true,
 
15
  "order": 80
16
  },
17
  "sections": [
12
  "premium": false,
13
  "run_if_whitelisted": false,
14
  "run_if_verified_bot": true,
15
+ "run_if_wpcli": false,
16
  "order": 80
17
  },
18
  "sections": [
src/config/feature-insights.php CHANGED
@@ -13,7 +13,8 @@
13
  "premium": false,
14
  "access_restricted": true,
15
  "run_if_whitelisted": true,
16
- "run_if_verified_bot": false
 
17
  },
18
  "requirements": {
19
  "php": {
13
  "premium": false,
14
  "access_restricted": true,
15
  "run_if_whitelisted": true,
16
+ "run_if_verified_bot": false,
17
+ "run_if_wpcli": false
18
  },
19
  "requirements": {
20
  "php": {
src/config/feature-ips.php CHANGED
@@ -12,6 +12,7 @@
12
  "premium": false,
13
  "run_if_whitelisted": true,
14
  "run_if_verified_bot": true,
 
15
  "order": 100
16
  },
17
  "admin_notices": {
12
  "premium": false,
13
  "run_if_whitelisted": true,
14
  "run_if_verified_bot": true,
15
+ "run_if_wpcli": false,
16
  "order": 100
17
  },
18
  "admin_notices": {
src/config/feature-license.php CHANGED
@@ -13,7 +13,8 @@
13
  "premium": false,
14
  "access_restricted": true,
15
  "run_if_whitelisted": true,
16
- "run_if_verified_bot": true
 
17
  },
18
  "sections": [
19
  {
13
  "premium": false,
14
  "access_restricted": true,
15
  "run_if_whitelisted": true,
16
+ "run_if_verified_bot": true,
17
+ "run_if_wpcli": true
18
  },
19
  "sections": [
20
  {
src/config/feature-lockdown.php CHANGED
@@ -12,6 +12,7 @@
12
  "premium": false,
13
  "run_if_whitelisted": false,
14
  "run_if_verified_bot": false,
 
15
  "order": 90
16
  },
17
  "sections": [
@@ -180,6 +181,7 @@
180
  "default_restapi_exclusions": [
181
  "contact-form-7",
182
  "jetpack",
 
183
  "wpstatistics",
184
  "woocommerce"
185
  ]
12
  "premium": false,
13
  "run_if_whitelisted": false,
14
  "run_if_verified_bot": false,
15
+ "run_if_wpcli": false,
16
  "order": 90
17
  },
18
  "sections": [
181
  "default_restapi_exclusions": [
182
  "contact-form-7",
183
  "jetpack",
184
+ "tho",
185
  "wpstatistics",
186
  "woocommerce"
187
  ]
src/config/feature-login_protect.php CHANGED
@@ -12,6 +12,7 @@
12
  "premium": false,
13
  "run_if_whitelisted": false,
14
  "run_if_verified_bot": false,
 
15
  "order": 40
16
  },
17
  "admin_notices": {
12
  "premium": false,
13
  "run_if_whitelisted": false,
14
  "run_if_verified_bot": false,
15
+ "run_if_wpcli": false,
16
  "order": 40
17
  },
18
  "admin_notices": {
src/config/feature-mousetrap.php ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "slug": "mousetrap",
3
+ "properties": {
4
+ "slug": "mousetrap",
5
+ "name": "MouseTrap",
6
+ "show_module_menu_item": false,
7
+ "show_module_options": true,
8
+ "storage_key": "mousetrap",
9
+ "tagline": "Identify, Trap and Block Bots",
10
+ "show_central": true,
11
+ "access_restricted": true,
12
+ "premium": false,
13
+ "run_if_whitelisted": false,
14
+ "run_if_verified_bot": false,
15
+ "order": 30
16
+ },
17
+ "sections": [
18
+ {
19
+ "slug": "section_cheese",
20
+ "primary": true,
21
+ "title": "Tempt Bots With Links",
22
+ "title_short": "Link Cheese",
23
+ "summary": [
24
+ "Recommendation - Enable to capture bots/spiders that don't honour 'nofollow' directives."
25
+ ]
26
+ },
27
+ {
28
+ "slug": "section_enable_plugin_feature_mousetrap",
29
+ "title": "Enable Module: MouseTrap",
30
+ "title_short": "Enable Module",
31
+ "summary": [
32
+ "Purpose - MouseTrap monitors a typical set of bot behaviours to help identify probing bots.",
33
+ "Recommendation - Enable as many mouse traps as possible."
34
+ ]
35
+ },
36
+ {
37
+ "slug": "section_non_ui",
38
+ "hidden": true
39
+ }
40
+ ],
41
+ "options": [
42
+ {
43
+ "key": "enable_mousetrap",
44
+ "section": "section_enable_plugin_feature_mousetrap",
45
+ "default": "Y",
46
+ "type": "checkbox",
47
+ "link_info": "",
48
+ "link_blog": "",
49
+ "name": "Enable MouseTrap",
50
+ "summary": "Enable (or Disable) The MouseTrap module",
51
+ "description": "Un-Checking this option will completely disable the MouseTrap module"
52
+ },
53
+ {
54
+ "key": "404_detect",
55
+ "section": "section_cheese",
56
+ "default": "disabled",
57
+ "type": "select",
58
+ "value_options": [
59
+ {
60
+ "value_key": "disabled",
61
+ "text": "Disabled"
62
+ },
63
+ {
64
+ "value_key": "transgression",
65
+ "text": "Increment Transgression"
66
+ },
67
+ {
68
+ "value_key": "block",
69
+ "text": "Immediate Block"
70
+ }
71
+ ],
72
+ "link_info": "",
73
+ "link_blog": "",
74
+ "name": "404 Detect",
75
+ "summary": "Identify A Bot When It Hits A 404",
76
+ "description": "Detect When A Visitor Browses To A Non-Existent Page."
77
+ },
78
+ {
79
+ "key": "link_cheese",
80
+ "section": "section_cheese",
81
+ "default": "transgression",
82
+ "type": "select",
83
+ "value_options": [
84
+ {
85
+ "value_key": "disabled",
86
+ "text": "Disabled"
87
+ },
88
+ {
89
+ "value_key": "transgression",
90
+ "text": "Increment Transgression"
91
+ },
92
+ {
93
+ "value_key": "block",
94
+ "text": "Immediate Block"
95
+ }
96
+ ],
97
+ "link_info": "",
98
+ "link_blog": "",
99
+ "name": "Link Cheese",
100
+ "summary": "Tempt A Bot With A Link To Follow",
101
+ "description": "Detect A Bot That Follows A 'no-follow' Link."
102
+ },
103
+ {
104
+ "key": "invalid_username",
105
+ "section": "section_cheese",
106
+ "default": "transgression",
107
+ "type": "select",
108
+ "value_options": [
109
+ {
110
+ "value_key": "disabled",
111
+ "text": "Disabled"
112
+ },
113
+ {
114
+ "value_key": "transgression",
115
+ "text": "Increment Transgression"
116
+ },
117
+ {
118
+ "value_key": "block",
119
+ "text": "Immediate Block"
120
+ }
121
+ ],
122
+ "link_info": "",
123
+ "link_blog": "",
124
+ "name": "Invalid Usernames",
125
+ "summary": "Detect Invalid Username Logins",
126
+ "description": "Identify A Bot When It Tries To Login With A Non-Existent Username."
127
+ },
128
+ {
129
+ "key": "fake_webcrawler",
130
+ "section": "section_cheese",
131
+ "default": "transgression",
132
+ "type": "select",
133
+ "value_options": [
134
+ {
135
+ "value_key": "disabled",
136
+ "text": "Disabled"
137
+ },
138
+ {
139
+ "value_key": "transgression",
140
+ "text": "Increment Transgression"
141
+ },
142
+ {
143
+ "value_key": "block",
144
+ "text": "Immediate Block"
145
+ }
146
+ ],
147
+ "link_info": "",
148
+ "link_blog": "",
149
+ "name": "Fake Web Crawler",
150
+ "summary": "Detect Fake Search Engine Crawlers",
151
+ "description": "Identify a Bot when it presents as an official web crawler, but analysis shows it's fake."
152
+ },
153
+ {
154
+ "key": "insights_last_firewall_block_at",
155
+ "transferable": false,
156
+ "section": "section_non_ui",
157
+ "default": 0
158
+ }
159
+ ],
160
+ "definitions": {
161
+ }
162
+ }
src/config/feature-plugin.php CHANGED
@@ -14,6 +14,7 @@
14
  "has_custom_actions": false,
15
  "run_if_whitelisted": true,
16
  "run_if_verified_bot": true,
 
17
  "order": 10
18
  },
19
  "admin_notices": {
@@ -50,7 +51,8 @@
50
  "schedule": "once",
51
  "valid_admin": true,
52
  "delay_days": 15,
53
- "type": "promo"
 
54
  },
55
  "rate-plugin": {
56
  "id": "rate-plugin",
@@ -531,9 +533,6 @@
531
  "license": {
532
  "title": "Go Pro"
533
  },
534
- "import": {
535
- "title": "Import"
536
- },
537
  "admin_access_restriction": {
538
  "title": "Security Admin"
539
  },
14
  "has_custom_actions": false,
15
  "run_if_whitelisted": true,
16
  "run_if_verified_bot": true,
17
+ "run_if_wpcli": true,
18
  "order": 10
19
  },
20
  "admin_notices": {
51
  "schedule": "once",
52
  "valid_admin": true,
53
  "delay_days": 15,
54
+ "type": "promo",
55
+ "twig": true
56
  },
57
  "rate-plugin": {
58
  "id": "rate-plugin",
533
  "license": {
534
  "title": "Go Pro"
535
  },
 
 
 
536
  "admin_access_restriction": {
537
  "title": "Security Admin"
538
  },
src/config/feature-sessions.php CHANGED
@@ -11,7 +11,8 @@
11
  "access_restricted": true,
12
  "auto_load_processor": true,
13
  "run_if_whitelisted": true,
14
- "run_if_verified_bot": true
 
15
  },
16
  "sections": [
17
  {
11
  "access_restricted": true,
12
  "auto_load_processor": true,
13
  "run_if_whitelisted": true,
14
+ "run_if_verified_bot": true,
15
+ "run_if_wpcli": false
16
  },
17
  "sections": [
18
  {
src/config/feature-statistics.php CHANGED
@@ -9,7 +9,8 @@
9
  "premium": false,
10
  "access_restricted": true,
11
  "run_if_whitelisted": true,
12
- "run_if_verified_bot": false
 
13
  },
14
  "sections": [
15
  {
9
  "premium": false,
10
  "access_restricted": true,
11
  "run_if_whitelisted": true,
12
+ "run_if_verified_bot": false,
13
+ "run_if_wpcli": false
14
  },
15
  "sections": [
16
  {
src/config/feature-traffic.php CHANGED
@@ -12,6 +12,7 @@
12
  "premium": true,
13
  "run_if_whitelisted": false,
14
  "run_if_verified_bot": true,
 
15
  "order": 110
16
  },
17
  "requirements": {
12
  "premium": true,
13
  "run_if_whitelisted": false,
14
  "run_if_verified_bot": true,
15
+ "run_if_wpcli": false,
16
  "order": 110
17
  },
18
  "requirements": {
src/config/feature-user_management.php CHANGED
@@ -11,6 +11,7 @@
11
  "premium": false,
12
  "run_if_whitelisted": false,
13
  "run_if_verified_bot": false,
 
14
  "order": 40
15
  },
16
  "sections": [
@@ -27,7 +28,6 @@
27
  {
28
  "slug": "section_passwords",
29
  "reqs": {
30
- "php_min": "5.4",
31
  "wp_min": "4.4"
32
  },
33
  "title": "Password Policies",
@@ -37,6 +37,16 @@
37
  "Recommendation - Use of this feature is highly recommend."
38
  ]
39
  },
 
 
 
 
 
 
 
 
 
 
40
  {
41
  "slug": "section_admin_login_notification",
42
  "title": "Admin Login Notification",
@@ -229,12 +239,50 @@
229
  "premium": true,
230
  "type": "integer",
231
  "default": "60",
 
232
  "link_info": "",
233
  "link_blog": "",
234
  "name": "Password Expiration",
235
  "summary": "Passwords Expire After This Many Days",
236
  "description": "Users will be forced to reset their passwords after the number of days specified."
237
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
  {
239
  "key": "autoadd_sessions_started_at",
240
  "section": "section_non_ui",
@@ -255,6 +303,13 @@
255
  "transferable": false,
256
  "type": "integer",
257
  "default": 0
 
 
 
 
 
 
 
258
  }
259
  ],
260
  "definitions": {
11
  "premium": false,
12
  "run_if_whitelisted": false,
13
  "run_if_verified_bot": false,
14
+ "run_if_wpcli": false,
15
  "order": 40
16
  },
17
  "sections": [
28
  {
29
  "slug": "section_passwords",
30
  "reqs": {
 
31
  "wp_min": "4.4"
32
  },
33
  "title": "Password Policies",
37
  "Recommendation - Use of this feature is highly recommend."
38
  ]
39
  },
40
+ {
41
+ "slug": "section_suspend",
42
+ "hidden": true,
43
+ "title": "Automatic And Manual User Suspension",
44
+ "title_short": "User Suspension",
45
+ "summary": [
46
+ "Purpose - Automatically suspend accounts to prevent login by certain users.",
47
+ "Recommendation - Use of this feature is highly recommend."
48
+ ]
49
+ },
50
  {
51
  "slug": "section_admin_login_notification",
52
  "title": "Admin Login Notification",
239
  "premium": true,
240
  "type": "integer",
241
  "default": "60",
242
+ "min": 0,
243
  "link_info": "",
244
  "link_blog": "",
245
  "name": "Password Expiration",
246
  "summary": "Passwords Expire After This Many Days",
247
  "description": "Users will be forced to reset their passwords after the number of days specified."
248
  },
249
+ {
250
+ "key": "manual_suspend",
251
+ "section": "section_suspend",
252
+ "premium": true,
253
+ "type": "checkbox",
254
+ "default": "Y",
255
+ "link_info": "",
256
+ "link_blog": "",
257
+ "name": "Allow Manual User Suspension",
258
+ "summary": "Manually Suspend User Accounts To Prevent Login",
259
+ "description": "Users may be suspended by administrators to prevent login."
260
+ },
261
+ {
262
+ "key": "auto_password",
263
+ "section": "section_suspend",
264
+ "premium": true,
265
+ "type": "checkbox",
266
+ "default": "Y",
267
+ "link_info": "",
268
+ "link_blog": "",
269
+ "name": "Auto-Suspend Expired Passwords",
270
+ "summary": "Automatically Suspend Users With Expired Passwords",
271
+ "description": "Suspend login by users and require password reset to unsuspend."
272
+ },
273
+ {
274
+ "key": "auto_idle",
275
+ "section": "section_suspend",
276
+ "premium": true,
277
+ "type": "integer",
278
+ "default": 0,
279
+ "min": 0,
280
+ "link_info": "",
281
+ "link_blog": "",
282
+ "name": "Auto-Suspend Idle Users",
283
+ "summary": "Automatically Suspend Idle User Accounts",
284
+ "description": "Prevent login by idle users and require password reset to unsuspend."
285
+ },
286
  {
287
  "key": "autoadd_sessions_started_at",
288
  "section": "section_non_ui",
303
  "transferable": false,
304
  "type": "integer",
305
  "default": 0
306
+ },
307
+ {
308
+ "key": "hard_suspended_userids",
309
+ "section": "section_non_ui",
310
+ "transferable": false,
311
+ "type": "array",
312
+ "default": []
313
  }
314
  ],
315
  "definitions": {
src/features/admin_access_restriction.php CHANGED
@@ -26,7 +26,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
26
  public function handleAuthAjax( $aAjaxResponse ) {
27
 
28
  if ( empty( $aAjaxResponse ) ) {
29
- switch ( $this->loadRequest()->request( 'exec' ) ) {
30
 
31
  case 'sec_admin_check':
32
  $aAjaxResponse = $this->ajaxExec_SecAdminCheck();
@@ -195,7 +195,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
195
  * @return array
196
  */
197
  public function getOptionsToRestrict( $sType = '' ) {
198
- $sType = empty( $sType ) ? ( $this->loadWp()->isMultisite() ? 'wpms' : 'wp' ) : 'wp';
199
  $aOptions = $this->getRestrictedOptions();
200
  return ( isset( $aOptions[ $sType.'_options' ] ) && is_array( $aOptions[ $sType.'_options' ] ) ) ? $aOptions[ $sType.'_options' ] : array();
201
  }
@@ -205,7 +205,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
205
  * @return array
206
  */
207
  public function getOptionsPagesToRestrict( $sType = '' ) {
208
- $sType = empty( $sType ) ? ( $this->loadWp()->isMultisite() ? 'wpms' : 'wp' ) : 'wp';
209
  $aOptions = $this->getRestrictedOptions();
210
  return ( isset( $aOptions[ $sType.'_pages' ] ) && is_array( $aOptions[ $sType.'_pages' ] ) ) ? $aOptions[ $sType.'_pages' ] : array();
211
  }
@@ -231,7 +231,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
231
  * @return bool
232
  */
233
  public function isRegisteredSecAdminUser() {
234
- $sUser = $this->loadWpUsers()->getCurrentWpUsername();
235
  return !empty( $sUser ) && in_array( $sUser, $this->getSecurityAdminUsers() );
236
  }
237
 
@@ -274,8 +274,8 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
274
  * @return string[]
275
  */
276
  private function verifySecAdminUsers( $aSecUsers ) {
277
- $oDP = $this->loadDP();
278
- $oWpUsers = $this->loadWpUsers();
279
 
280
  $aFiltered = array();
281
  foreach ( $aSecUsers as $nCurrentKey => $sUsernameOrEmail ) {
@@ -342,7 +342,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
342
  $nLeft = 0;
343
  }
344
  else if ( $nSecAdminAt > 0 ) {
345
- $nLeft = $this->getSecAdminTimeout() - ( $this->loadRequest()->ts() - $nSecAdminAt );
346
  }
347
  }
348
  return max( 0, $nLeft );
@@ -383,10 +383,18 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
383
  * @return bool
384
  */
385
  public function checkAdminAccessKeySubmission() {
386
- $sAccessKeyRequest = $this->loadRequest()->post( 'admin_access_key_request', '' );
387
- $bSuccess = $this->verifyAccessKey( $sAccessKeyRequest );
388
- if ( !$bSuccess && !empty( $sAccessKeyRequest ) ) {
389
- $this->setIpTransgressed();
 
 
 
 
 
 
 
 
390
  }
391
  return $bSuccess;
392
  }
@@ -395,7 +403,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
395
  * @return bool
396
  */
397
  protected function isAccessKeyRequest() {
398
- return strlen( $this->loadRequest()->post( 'admin_access_key_request', '' ) ) > 0;
399
  }
400
 
401
  /**
@@ -879,7 +887,7 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
879
  public function preDeactivatePlugin() {
880
  $oCon = $this->getCon();
881
  if ( !$oCon->isPluginAdmin() ) {
882
- $this->loadWp()->wpDie(
883
  _wpsf__( "Sorry, this plugin is protected against unauthorised attempts to disable it." )
884
  .'<br />'.sprintf( '<a href="%s">%s</a>',
885
  $this->getUrl_AdminPage(),
@@ -888,12 +896,4 @@ class ICWP_WPSF_FeatureHandler_AdminAccessRestriction extends ICWP_WPSF_FeatureH
888
  );
889
  }
890
  }
891
-
892
- /**
893
- * @deprecated v6.10.7
894
- * @return bool
895
- */
896
- public function doCheckHasPermissionToSubmit() {
897
- return $this->getCon()->isPluginAdmin();
898
- }
899
  }
26
  public function handleAuthAjax( $aAjaxResponse ) {
27
 
28
  if ( empty( $aAjaxResponse ) ) {
29
+ switch ( Services::Request()->request( 'exec' ) ) {
30
 
31
  case 'sec_admin_check':
32
  $aAjaxResponse = $this->ajaxExec_SecAdminCheck();
195
  * @return array
196
  */
197
  public function getOptionsToRestrict( $sType = '' ) {
198
+ $sType = empty( $sType ) ? ( Services::WpGeneral()->isMultisite() ? 'wpms' : 'wp' ) : 'wp';
199
  $aOptions = $this->getRestrictedOptions();
200
  return ( isset( $aOptions[ $sType.'_options' ] ) && is_array( $aOptions[ $sType.'_options' ] ) ) ? $aOptions[ $sType.'_options' ] : array();
201
  }
205
  * @return array
206
  */
207
  public function getOptionsPagesToRestrict( $sType = '' ) {
208
+ $sType = empty( $sType ) ? ( Services::WpGeneral()->isMultisite() ? 'wpms' : 'wp' ) : 'wp';
209
  $aOptions = $this->getRestrictedOptions();
210
  return ( isset( $aOptions[ $sType.'_pages' ] ) && is_array( $aOptions[ $sType.'_pages' ] ) ) ? $aOptions[ $sType.'_pages' ] : array();
211
  }
231
  * @return bool
232
  */
233
  public function isRegisteredSecAdminUser() {
234
+ $sUser = Services::WpUsers()->getCurrentWpUsername();
235
  return !empty( $sUser ) && in_array( $sUser, $this->getSecurityAdminUsers() );
236
  }
237
 
274
  * @return string[]
275
  */
276
  private function verifySecAdminUsers( $aSecUsers ) {
277
+ $oDP = Services::Data();
278
+ $oWpUsers = Services::WpUsers();
279
 
280
  $aFiltered = array();
281
  foreach ( $aSecUsers as $nCurrentKey => $sUsernameOrEmail ) {
342
  $nLeft = 0;
343
  }
344
  else if ( $nSecAdminAt > 0 ) {
345
+ $nLeft = $this->getSecAdminTimeout() - ( Services::Request()->ts() - $nSecAdminAt );
346
  }
347
  }
348
  return max( 0, $nLeft );
383
  * @return bool
384
  */
385
  public function checkAdminAccessKeySubmission() {
386
+ $bSuccess = false;
387
+ $oReq = Services::Request();
388
+ $sAccessKeyRequest = $oReq->post( 'admin_access_key_request', '' );
389
+ if ( !empty( $sAccessKeyRequest ) ) {
390
+ // Made the hither-to unknown discovery that WordPress magic quotes all $_POST variables
391
+ // So the Admin Password initially provided may have been escaped with "\"
392
+ // The 1st approach uses raw, unescaped. The 2nd approach uses the older escaped $_POST.
393
+ $bSuccess = $this->verifyAccessKey( $sAccessKeyRequest )
394
+ || $this->verifyAccessKey( $oReq->post( 'admin_access_key_request', '' ) );
395
+ if ( !$bSuccess ) {
396
+ $this->setIpTransgressed();
397
+ }
398
  }
399
  return $bSuccess;
400
  }
403
  * @return bool
404
  */
405
  protected function isAccessKeyRequest() {
406
+ return strlen( Services::Request()->post( 'admin_access_key_request', '' ) ) > 0;
407
  }
408
 
409
  /**
887
  public function preDeactivatePlugin() {
888
  $oCon = $this->getCon();
889
  if ( !$oCon->isPluginAdmin() ) {
890
+ Services::WpGeneral()->wpDie(
891
  _wpsf__( "Sorry, this plugin is protected against unauthorised attempts to disable it." )
892
  .'<br />'.sprintf( '<a href="%s">%s</a>',
893
  $this->getUrl_AdminPage(),
896
  );
897
  }
898
  }
 
 
 
 
 
 
 
 
899
  }
src/features/audit_trail.php CHANGED
@@ -19,7 +19,7 @@ class ICWP_WPSF_FeatureHandler_AuditTrail extends ICWP_WPSF_FeatureHandler_BaseW
19
  public function handleAuthAjax( $aAjaxResponse ) {
20
 
21
  if ( empty( $aAjaxResponse ) ) {
22
- switch ( $this->loadRequest()->request( 'exec' ) ) {
23
 
24
  case 'render_table_audittrail':
25
  $aAjaxResponse = $this->ajaxExec_BuildTableAuditTrail();
@@ -42,7 +42,7 @@ class ICWP_WPSF_FeatureHandler_AuditTrail extends ICWP_WPSF_FeatureHandler_BaseW
42
  protected function ajaxExec_AddParamToFirewallWhitelist() {
43
  $bSuccess = false;
44
 
45
- $nId = $this->loadRequest()->post( 'rid' );
46
  if ( empty( $nId ) || !is_numeric( $nId ) || $nId < 1 ) {
47
  $sMessage = _wpsf__( 'Invalid audit entry selected for this action' );
48
  }
@@ -215,6 +215,55 @@ class ICWP_WPSF_FeatureHandler_AuditTrail extends ICWP_WPSF_FeatureHandler_BaseW
215
  );
216
  }
217
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  /**
219
  * See plugin controller for the nature of $aData wpPrivacyExport()
220
  *
@@ -227,7 +276,7 @@ class ICWP_WPSF_FeatureHandler_AuditTrail extends ICWP_WPSF_FeatureHandler_BaseW
227
  /** @var ICWP_WPSF_Processor_AuditTrail $oProc */
228
  $oProc = $this->getProcessor();
229
 
230
- $oUser = $this->loadWpUsers()->getUserByEmail( $sEmail );
231
 
232
  $aExportItem = array(
233
  'group_id' => $this->prefix(),
@@ -243,7 +292,7 @@ class ICWP_WPSF_FeatureHandler_AuditTrail extends ICWP_WPSF_FeatureHandler_BaseW
243
  ->addWhereSearch( 'wp_username', $oUser->user_login )
244
  ->setResultsAsVo( true );
245
 
246
- $oWp = $this->loadWp();
247
  /** @var Shield\Databases\AuditTrail\EntryVO $oEntry */
248
  foreach ( $oFinder->query() as $oEntry ) {
249
  $aExportItem[ 'data' ][] = array(
@@ -277,7 +326,7 @@ class ICWP_WPSF_FeatureHandler_AuditTrail extends ICWP_WPSF_FeatureHandler_BaseW
277
  $oProc = $this->getProcessor();
278
 
279
  try {
280
- $oThisUsername = $this->loadWpUsers()->getUserByEmail( $sEmail )->user_login;
281
  $oProc->getSubProAuditor()
282
  ->getDbHandler()
283
  ->getQueryDeleter()
@@ -391,16 +440,31 @@ class ICWP_WPSF_FeatureHandler_AuditTrail extends ICWP_WPSF_FeatureHandler_BaseW
391
  sprintf( '%s - %s', _wpsf__( 'Purpose' ), _wpsf__( 'Provides finer control over the audit trail itself.' ) ),
392
  sprintf( '%s - %s', _wpsf__( 'Recommendation' ), _wpsf__( 'These settings are dependent on your requirements.' ) )
393
  );
394
- $sTitleShort = _wpsf__( 'Options' );
395
  break;
396
 
397
  case 'section_enable_audit_contexts' :
398
- $sTitle = _wpsf__( 'Enable Audit Contexts' );
399
  $aSummary = array(
400
  sprintf( '%s - %s', _wpsf__( 'Purpose' ), _wpsf__( 'Specify which types of actions on your site are logged.' ) ),
401
  sprintf( '%s - %s', _wpsf__( 'Recommendation' ), _wpsf__( 'These settings are dependent on your requirements.' ) )
402
  );
403
- $sTitleShort = _wpsf__( 'Audit Contexts' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
404
  break;
405
 
406
  default:
@@ -438,7 +502,7 @@ class ICWP_WPSF_FeatureHandler_AuditTrail extends ICWP_WPSF_FeatureHandler_BaseW
438
 
439
  case 'audit_trail_auto_clean' :
440
  $sName = _wpsf__( 'Auto Clean' );
441
- $sSummary = _wpsf__( 'Enable Audit Auto Cleaning' );
442
  $sDescription = _wpsf__( 'Events older than the number of days specified will be automatically cleaned from the database.' );
443
  break;
444
 
@@ -484,6 +548,27 @@ class ICWP_WPSF_FeatureHandler_AuditTrail extends ICWP_WPSF_FeatureHandler_BaseW
484
  $sDescription = sprintf( _wpsf__( 'When this context is enabled, the audit trail will track activity relating to: %s' ), $oCon->getHumanName() );
485
  break;
486
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
487
  default:
488
  throw new \Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
489
  }
19
  public function handleAuthAjax( $aAjaxResponse ) {
20
 
21
  if ( empty( $aAjaxResponse ) ) {
22
+ switch ( Services::Request()->request( 'exec' ) ) {
23
 
24
  case 'render_table_audittrail':
25
  $aAjaxResponse = $this->ajaxExec_BuildTableAuditTrail();
42
  protected function ajaxExec_AddParamToFirewallWhitelist() {
43
  $bSuccess = false;
44
 
45
+ $nId = Services::Request()->post( 'rid' );
46
  if ( empty( $nId ) || !is_numeric( $nId ) || $nId < 1 ) {
47
  $sMessage = _wpsf__( 'Invalid audit entry selected for this action' );
48
  }
215
  );
216
  }
217
 
218
+ /**
219
+ * @return bool
220
+ */
221
+ public function isEnabledChangeTracking() {
222
+ return !$this->isOpt( 'enable_change_tracking', 'disabled' );
223
+ }
224
+
225
+ /**
226
+ * @return int
227
+ */
228
+ public function getCTSnapshotsPerWeek() {
229
+ return (int)$this->getOpt( 'ct_snapshots_per_week', 7 );
230
+ }
231
+
232
+ /**
233
+ * @return int
234
+ */
235
+ public function getCTMaxSnapshots() {
236
+ return (int)$this->getOpt( 'ct_max_snapshots', 28 );
237
+ }
238
+
239
+ /**
240
+ * @return int
241
+ */
242
+ public function getCTSnapshotInterval() {
243
+ return WEEK_IN_SECONDS/$this->getCTSnapshotsPerWeek();
244
+ }
245
+
246
+ /**
247
+ * @return int
248
+ */
249
+ public function getCTLastSnapshotAt() {
250
+ return $this->getOpt( 'ct_last_snapshot_at' );
251
+ }
252
+
253
+ /**
254
+ * @return bool
255
+ */
256
+ public function isCTSnapshotDue() {
257
+ return ( Services::Request()->ts() - $this->getCTLastSnapshotAt() > $this->getCTSnapshotInterval() );
258
+ }
259
+
260
+ /**
261
+ * @return ICWP_WPSF_FeatureHandler_AuditTrail
262
+ */
263
+ public function updateCTLastSnapshotAt() {
264
+ return $this->setOptAt( 'ct_last_snapshot_at' );
265
+ }
266
+
267
  /**
268
  * See plugin controller for the nature of $aData wpPrivacyExport()
269
  *
276
  /** @var ICWP_WPSF_Processor_AuditTrail $oProc */
277
  $oProc = $this->getProcessor();
278
 
279
+ $oUser = Services::WpUsers()->getUserByEmail( $sEmail );
280
 
281
  $aExportItem = array(
282
  'group_id' => $this->prefix(),
292
  ->addWhereSearch( 'wp_username', $oUser->user_login )
293
  ->setResultsAsVo( true );
294
 
295
+ $oWp = Services::WpGeneral();
296
  /** @var Shield\Databases\AuditTrail\EntryVO $oEntry */
297
  foreach ( $oFinder->query() as $oEntry ) {
298
  $aExportItem[ 'data' ][] = array(
326
  $oProc = $this->getProcessor();
327
 
328
  try {
329
+ $oThisUsername = Services::WpUsers()->getUserByEmail( $sEmail )->user_login;
330
  $oProc->getSubProAuditor()
331
  ->getDbHandler()
332
  ->getQueryDeleter()
440
  sprintf( '%s - %s', _wpsf__( 'Purpose' ), _wpsf__( 'Provides finer control over the audit trail itself.' ) ),
441
  sprintf( '%s - %s', _wpsf__( 'Recommendation' ), _wpsf__( 'These settings are dependent on your requirements.' ) )
442
  );
443
+ $sTitleShort = _wpsf__( 'Audit Trail Options' );
444
  break;
445
 
446
  case 'section_enable_audit_contexts' :
447
+ $sTitle = _wpsf__( 'Enable Audit Areas' );
448
  $aSummary = array(
449
  sprintf( '%s - %s', _wpsf__( 'Purpose' ), _wpsf__( 'Specify which types of actions on your site are logged.' ) ),
450
  sprintf( '%s - %s', _wpsf__( 'Recommendation' ), _wpsf__( 'These settings are dependent on your requirements.' ) )
451
  );
452
+ $sTitleShort = _wpsf__( 'Audit Areas' );
453
+ break;
454
+
455
+ case 'section_change_tracking' :
456
+ $sTitle = _wpsf__( 'Track All Major Changes To Your Site' );
457
+ $sTitleShort = _wpsf__( 'Change Tracking' );
458
+ $aData = ( new Shield\ChangeTrack\Snapshot\Collate() )->run();
459
+ $sResult = (int)( strlen( base64_encode( WP_Http_Encoding::compress( json_encode( $aData ) ) ) )/1024 );
460
+ $aSummary = array(
461
+ sprintf( '%s - %s', _wpsf__( 'Purpose' ), _wpsf__( 'Track significant changes to your site.' ) )
462
+ .' '.sprintf( '%s - %s', _wpsf__( 'Note' ), _wpsf__( 'This is separate from the Audit Trail.' ) ),
463
+ sprintf( '%s - %s', _wpsf__( 'Considerations' ),
464
+ _wpsf__( 'Change Tracking uses snapshots that may use take up lot of data.' )
465
+ .' '.sprintf( 'Each snapshot will consume ~%sKB in your database', $sResult )
466
+ ),
467
+ );
468
  break;
469
 
470
  default:
502
 
503
  case 'audit_trail_auto_clean' :
504
  $sName = _wpsf__( 'Auto Clean' );
505
+ $sSummary = _wpsf__( 'Enable Change Tracking' );
506
  $sDescription = _wpsf__( 'Events older than the number of days specified will be automatically cleaned from the database.' );
507
  break;
508
 
548
  $sDescription = sprintf( _wpsf__( 'When this context is enabled, the audit trail will track activity relating to: %s' ), $oCon->getHumanName() );
549
  break;
550
 
551
+ case 'enable_change_tracking' :
552
+ $sName = _wpsf__( 'Site Change Tracking' );
553
+ $sSummary = _wpsf__( 'Track Major Changes To Your Site' );
554
+ $sDescription = _wpsf__( 'Tracking major changes to your site will help you monitor and catch malicious damage.' );
555
+ break;
556
+
557
+ case 'ct_snapshots_per_week' :
558
+ $sName = _wpsf__( 'Snapshot Per Week' );
559
+ $sSummary = _wpsf__( 'Number Of Snapshots To Take Per Week' );
560
+ $sDescription = _wpsf__( 'The number of snapshots to take per week. For daily snapshots, select 7.' )
561
+ .'<br />'._wpsf__( 'Data storage in your database increases with the number of snapshots.' )
562
+ .'<br />'._wpsf__( 'However, increased snapshots provide more granular information on when major site changes occurred.' );
563
+ break;
564
+
565
+ case 'ct_max_snapshots' :
566
+ $sName = _wpsf__( 'Max Snapshots' );
567
+ $sSummary = _wpsf__( 'Maximum Number Of Snapshots To Retain' );
568
+ $sDescription = _wpsf__( 'The more snapshots you retain, the further back you can look at changes over your site.' )
569
+ .'<br />'._wpsf__( 'You will need to consider the implications to database storage requirements.' );
570
+ break;
571
+
572
  default:
573
  throw new \Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
574
  }
src/features/autoupdates.php CHANGED
@@ -1,12 +1,14 @@
1
  <?php
2
 
 
 
3
  class ICWP_WPSF_FeatureHandler_Autoupdates extends ICWP_WPSF_FeatureHandler_BaseWpsf {
4
 
5
  /**
6
  */
7
  protected function setupCustomHooks() {
8
  // Force run automatic updates
9
- if ( $this->loadRequest()->query( 'force_run_auto_updates' ) == 'now' ) {
10
  add_filter( $this->prefix( 'force_autoupdate' ), '__return_true' );
11
  }
12
  }
@@ -112,7 +114,7 @@ class ICWP_WPSF_FeatureHandler_Autoupdates extends ICWP_WPSF_FeatureHandler_Base
112
  public function handleAuthAjax( $aAjaxResponse ) {
113
 
114
  if ( empty( $aAjaxResponse ) ) {
115
- switch ( $this->loadRequest()->request( 'exec' ) ) {
116
 
117
  case 'toggle_plugin_autoupdate':
118
  $aAjaxResponse = $this->ajaxExec_TogglePluginAutoupdate();
@@ -134,7 +136,7 @@ class ICWP_WPSF_FeatureHandler_Autoupdates extends ICWP_WPSF_FeatureHandler_Base
134
 
135
  if ( $this->isAutoupdateIndividualPlugins() && $this->getCon()->isPluginAdmin() ) {
136
  $oWpPlugins = $this->loadWpPlugins();
137
- $sFile = $this->loadRequest()->post( 'pluginfile' );
138
  if ( $oWpPlugins->isInstalled( $sFile ) ) {
139
  $this->setPluginToAutoUpdate( $sFile );
140
 
@@ -206,7 +208,7 @@ class ICWP_WPSF_FeatureHandler_Autoupdates extends ICWP_WPSF_FeatureHandler_Base
206
  'messages' => array()
207
  );
208
  { //really disabled?
209
- $oWp = $this->loadWp();
210
  if ( $this->isModOptEnabled() ) {
211
  if ( $this->isDisableAllAutoUpdates() && !$oWp->getWpAutomaticUpdater()->is_disabled() ) {
212
  $aNotices[ 'messages' ][ 'disabled_auto' ] = array(
1
  <?php
2
 
3
+ use FernleafSystems\Wordpress\Services\Services;
4
+
5
  class ICWP_WPSF_FeatureHandler_Autoupdates extends ICWP_WPSF_FeatureHandler_BaseWpsf {
6
 
7
  /**
8
  */
9
  protected function setupCustomHooks() {
10
  // Force run automatic updates
11
+ if ( Services::Request()->query( 'force_run_auto_updates' ) == 'now' ) {
12
  add_filter( $this->prefix( 'force_autoupdate' ), '__return_true' );
13
  }
14
  }
114
  public function handleAuthAjax( $aAjaxResponse ) {
115
 
116
  if ( empty( $aAjaxResponse ) ) {
117
+ switch ( Services::Request()->request( 'exec' ) ) {
118
 
119
  case 'toggle_plugin_autoupdate':
120
  $aAjaxResponse = $this->ajaxExec_TogglePluginAutoupdate();
136
 
137
  if ( $this->isAutoupdateIndividualPlugins() && $this->getCon()->isPluginAdmin() ) {
138
  $oWpPlugins = $this->loadWpPlugins();
139
+ $sFile = Services::Request()->post( 'pluginfile' );
140
  if ( $oWpPlugins->isInstalled( $sFile ) ) {
141
  $this->setPluginToAutoUpdate( $sFile );
142
 
208
  'messages' => array()
209
  );
210
  { //really disabled?
211
+ $oWp = Services::WpGeneral();
212
  if ( $this->isModOptEnabled() ) {
213
  if ( $this->isDisableAllAutoUpdates() && !$oWp->getWpAutomaticUpdater()->is_disabled() ) {
214
  $aNotices[ 'messages' ][ 'disabled_auto' ] = array(
src/features/base.php CHANGED
@@ -82,7 +82,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
82
  * @param array $aModProps
83
  */
84
  protected function setupHooks( $aModProps ) {
85
- $oReq = $this->loadRequest();
86
 
87
  $nRunPriority = isset( $aModProps[ 'load_priority' ] ) ? $aModProps[ 'load_priority' ] : 100;
88
  add_action( $this->prefix( 'run_processors' ), array( $this, 'onRunProcessors' ), $nRunPriority );
@@ -163,7 +163,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
163
  public function handleAuthAjax( $aAjaxResponse ) {
164
 
165
  if ( empty( $aAjaxResponse ) ) {
166
- switch ( $this->loadRequest()->request( 'exec' ) ) {
167
 
168
  case 'mod_options':
169
  $aAjaxResponse = $this->ajaxExec_ModOptions();
@@ -215,9 +215,12 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
215
  * @return array
216
  */
217
  protected function getAjaxFormParams( $bBase64Encoded = false ) {
218
- $sRaw = $this->loadRequest()->post( 'form_params', '' );
219
- parse_str( ( $bBase64Encoded ? base64_decode( $sRaw ) : $sRaw ), $aFormParams );
220
- return is_array( $aFormParams ) ? $aFormParams : [];
 
 
 
221
  }
222
 
223
  /**
@@ -241,8 +244,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
241
  if ( !empty( $aPhpReqs ) ) {
242
 
243
  if ( !empty( $aPhpReqs[ 'version' ] ) ) {
244
- $bMeetsReqs = $bMeetsReqs && $this->loadDP()
245
- ->getPhpVersionIsAtLeast( $aPhpReqs[ 'version' ] );
246
  }
247
  if ( !empty( $aPhpReqs[ 'functions' ] ) && is_array( $aPhpReqs[ 'functions' ] ) ) {
248
  foreach ( $aPhpReqs[ 'functions' ] as $sFunction ) {
@@ -397,7 +399,6 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
397
  * @return bool
398
  */
399
  public function isUpgrading() {
400
- // return $this->getVersion() != $this->getController()->getVersion();
401
  return $this->getCon()->getIsRebuildOptionsFromFile() || $this->getOptionsVo()->getRebuildFromFile();
402
  }
403
 
@@ -418,7 +419,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
418
  }
419
 
420
  /**
421
- * @return ICWP_WPSF_Processor_Base
422
  */
423
  public function getProcessor() {
424
  return $this->loadProcessor();
@@ -428,11 +429,11 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
428
  * @return string
429
  */
430
  public function getUrl_AdminPage() {
431
- return $this->loadWp()
432
- ->getUrl_AdminPage(
433
- $this->getModSlug(),
434
- $this->getCon()->getIsWpmsNetworkAdminOnly()
435
- );
436
  }
437
 
438
  /**
@@ -463,6 +464,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
463
  /**
464
  * TODO: Get rid of this crap and/or handle the \Exception thrown in loadFeatureHandler()
465
  * @return ICWP_WPSF_FeatureHandler_Email
 
466
  */
467
  public function getEmailHandler() {
468
  if ( is_null( self::$oEmailHandler ) ) {
@@ -701,15 +703,6 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
701
  return $this->getOptionsVo()->getFeatureDefinition( $sKey );
702
  }
703
 
704
- /**
705
- * @deprecated
706
- * @param string $sKey
707
- * @return mixed|null
708
- */
709
- public function getDefinition( $sKey ) {
710
- return $this->getDef( $sKey );
711
- }
712
-
713
  /**
714
  * @return $this
715
  */
@@ -829,7 +822,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
829
  * @return bool
830
  */
831
  protected function isModuleRequest() {
832
- return ( $this->getModSlug() == $this->loadRequest()->request( 'mod_slug' ) );
833
  }
834
 
835
  /**
@@ -993,7 +986,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
993
  * @return array
994
  */
995
  protected function getSectionNotices( $sSectionSlug ) {
996
- return array();
997
  }
998
 
999
  /**
@@ -1001,7 +994,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1001
  * @return array
1002
  */
1003
  protected function getSectionWarnings( $sSection ) {
1004
- return array();
1005
  }
1006
 
1007
  /**
@@ -1212,7 +1205,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1212
  * @return bool
1213
  */
1214
  protected function isAdminOptionsPage() {
1215
- return ( is_admin() && !$this->loadWp()->isAjax() && $this->isThisModulePage() );
1216
  }
1217
 
1218
  /**
@@ -1293,7 +1286,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1293
  $sOptionValue = array_filter( explode( "\n", esc_textarea( $sOptionValue ) ), 'trim' );
1294
  }
1295
  else if ( $sOptType == 'comma_separated_lists' ) {
1296
- $sOptionValue = $this->loadDP()->extractCommaSeparatedList( $sOptionValue );
1297
  }
1298
  else if ( $sOptType == 'multiple_select' ) {
1299
  }
@@ -1310,7 +1303,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1310
  // only use this flag when the options are being updated with a MANUAL save.
1311
  if ( isset( $this->bImportExportWhitelistNotify ) && $this->bImportExportWhitelistNotify ) {
1312
  if ( !wp_next_scheduled( $this->prefix( 'importexport_notify' ) ) ) {
1313
- wp_schedule_single_event( $this->loadRequest()->ts() + 15, $this->prefix( 'importexport_notify' ) );
1314
  }
1315
  }
1316
  }
@@ -1330,21 +1323,21 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1330
  * @return bool
1331
  */
1332
  public function isThisModulePage() {
1333
- return $this->getCon()->isModulePage() && $this->loadRequest()->query( 'page' ) == $this->getModSlug();
1334
  }
1335
 
1336
  /**
1337
  * @return bool
1338
  */
1339
  protected function isModuleOptionsRequest() {
1340
- return $this->loadRequest()->post( 'mod_slug' ) === $this->getModSlug();
1341
  }
1342
 
1343
  /**
1344
  * @return bool
1345
  */
1346
  protected function isWizardPage() {
1347
- return ( $this->loadRequest()->query( 'shield_action' ) == 'wizard' && $this->isThisModulePage() );
1348
  }
1349
 
1350
  /**
@@ -1433,7 +1426,7 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1433
  'nonce_field' => wp_nonce_field( $oCon->getPluginPrefix(), '_wpnonce', true, false ), //don't echo!
1434
  'form_action' => 'admin.php?page='.$this->getModSlug(),
1435
  'nOptionsPerRow' => 1,
1436
- 'aPluginLabels' => $oCon->getPluginLabels(),
1437
  'help_video' => array(
1438
  'auto_show' => $this->getIfAutoShowHelpVideo(),
1439
  'iframe_url' => $this->getHelpVideoUrl( $this->getHelpVideoId() ),
@@ -1568,10 +1561,10 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1568
  public function getUrl_Wizard( $sWizardSlug ) {
1569
  $aDef = $this->getWizardDefinition( $sWizardSlug );
1570
  if ( empty( $aDef[ 'min_user_permissions' ] ) ) { // i.e. no login/minimum perms
1571
- $sUrl = $this->loadWp()->getHomeUrl();
1572
  }
1573
  else {
1574
- $sUrl = $this->loadWp()->getUrl_WpAdmin( 'admin.php' );
1575
  }
1576
 
1577
  return add_query_arg(
@@ -1949,18 +1942,10 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1949
  * @return $this
1950
  */
1951
  protected function setOptAt( $sOpt, $nAt = null ) {
1952
- $nAt = is_null( $nAt ) ? $this->loadRequest()->ts() : max( 0, (int)$nAt );
1953
  return $this->setOpt( $sOpt, $nAt );
1954
  }
1955
 
1956
- /**
1957
- * @deprecated since 6.9
1958
- * @return string
1959
- */
1960
- public function getFeatureSlug() {
1961
- return $this->getSlug();
1962
- }
1963
-
1964
  /**
1965
  * @deprecated
1966
  * @return string
@@ -1968,52 +1953,4 @@ abstract class ICWP_WPSF_FeatureHandler_Base extends ICWP_WPSF_Foundation {
1968
  public function getVersion() {
1969
  return $this->getCon()->getVersion();
1970
  }
1971
-
1972
- /**
1973
- * @deprecated since v7 as all are 5.4+
1974
- * @return bool
1975
- */
1976
- public function canRunWizards() {
1977
- return true;
1978
- }
1979
-
1980
- /**
1981
- * @deprecated
1982
- * @return ICWP_WPSF_Plugin_Controller
1983
- */
1984
- static public function getConn() {
1985
- return self::$oPluginController;
1986
- }
1987
-
1988
- /**
1989
- * @deprecated v7
1990
- * @return ICWP_WPSF_Plugin_Controller
1991
- */
1992
- static public function getController() {
1993
- return self::getConn();
1994
- }
1995
-
1996
- /**
1997
- * @deprecated
1998
- * @return bool
1999
- */
2000
- protected function getModuleMeetRequirements() {
2001
- return $this->verifyModuleMeetRequirements();
2002
- }
2003
-
2004
- /**
2005
- * @deprecated
2006
- * @return bool
2007
- */
2008
- public function isPluginDeleting() {
2009
- return $this->getCon()->isPluginDeleting();
2010
- }
2011
-
2012
- /**
2013
- * @deprecated
2014
- * @throws \Exception
2015
- */
2016
- protected function updatePluginOptionsFromSubmit() {
2017
- $this->doSaveStandardOptions();
2018
- }
2019
  }
82
  * @param array $aModProps
83
  */
84
  protected function setupHooks( $aModProps ) {
85
+ $oReq = Services::Request();
86
 
87
  $nRunPriority = isset( $aModProps[ 'load_priority' ] ) ? $aModProps[ 'load_priority' ] : 100;
88
  add_action( $this->prefix( 'run_processors' ), array( $this, 'onRunProcessors' ), $nRunPriority );
163
  public function handleAuthAjax( $aAjaxResponse ) {
164
 
165
  if ( empty( $aAjaxResponse ) ) {
166
+ switch ( Services::Request()->request( 'exec' ) ) {
167
 
168
  case 'mod_options':
169
  $aAjaxResponse = $this->ajaxExec_ModOptions();
215
  * @return array
216
  */
217
  protected function getAjaxFormParams( $bBase64Encoded = false ) {
218
+ $aFormParams = [];
219
+ $sRaw = Services::Request()->post( 'form_params', '' );
220
+ if ( !empty( $sRaw ) ) {
221
+ parse_str( ( $bBase64Encoded ? base64_decode( $sRaw ) : $sRaw ), $aFormParams );
222
+ }
223
+ return $aFormParams;
224
  }
225
 
226
  /**
244
  if ( !empty( $aPhpReqs ) ) {
245
 
246
  if ( !empty( $aPhpReqs[ 'version' ] ) ) {
247
+ $bMeetsReqs = $bMeetsReqs && Services::Data()->getPhpVersionIsAtLeast( $aPhpReqs[ 'version' ] );
 
248
  }
249
  if ( !empty( $aPhpReqs[ 'functions' ] ) && is_array( $aPhpReqs[ 'functions' ] ) ) {
250
  foreach ( $aPhpReqs[ 'functions' ] as $sFunction ) {
399
  * @return bool
400
  */
401
  public function isUpgrading() {
 
402
  return $this->getCon()->getIsRebuildOptionsFromFile() || $this->getOptionsVo()->getRebuildFromFile();
403
  }
404
 
419
  }
420
 
421
  /**
422
+ * @return ICWP_WPSF_Processor_Base|mixed
423
  */
424
  public function getProcessor() {
425
  return $this->loadProcessor();
429
  * @return string
430
  */
431
  public function getUrl_AdminPage() {
432
+ return Services::WpGeneral()
433
+ ->getUrl_AdminPage(
434
+ $this->getModSlug(),
435
+ $this->getCon()->getIsWpmsNetworkAdminOnly()
436
+ );
437
  }
438
 
439
  /**
464
  /**
465
  * TODO: Get rid of this crap and/or handle the \Exception thrown in loadFeatureHandler()
466
  * @return ICWP_WPSF_FeatureHandler_Email
467
+ * @throws \Exception
468
  */
469
  public function getEmailHandler() {
470
  if ( is_null( self::$oEmailHandler ) ) {
703
  return $this->getOptionsVo()->getFeatureDefinition( $sKey );
704
  }
705
 
 
 
 
 
 
 
 
 
 
706
  /**
707
  * @return $this
708
  */
822
  * @return bool
823
  */
824
  protected function isModuleRequest() {
825
+ return ( $this->getModSlug() == Services::Request()->request( 'mod_slug' ) );
826
  }
827
 
828
  /**
986
  * @return array
987
  */
988
  protected function getSectionNotices( $sSectionSlug ) {
989
+ return [];
990
  }
991
 
992
  /**
994
  * @return array
995
  */
996
  protected function getSectionWarnings( $sSection ) {
997
+ return [];
998
  }
999
 
1000
  /**
1205
  * @return bool
1206
  */
1207
  protected function isAdminOptionsPage() {
1208
+ return ( is_admin() && !Services::WpGeneral()->isAjax() && $this->isThisModulePage() );
1209
  }
1210
 
1211
  /**
1286
  $sOptionValue = array_filter( explode( "\n", esc_textarea( $sOptionValue ) ), 'trim' );
1287
  }
1288
  else if ( $sOptType == 'comma_separated_lists' ) {
1289
+ $sOptionValue = Services::Data()->extractCommaSeparatedList( $sOptionValue );
1290
  }
1291
  else if ( $sOptType == 'multiple_select' ) {
1292
  }
1303
  // only use this flag when the options are being updated with a MANUAL save.
1304
  if ( isset( $this->bImportExportWhitelistNotify ) && $this->bImportExportWhitelistNotify ) {
1305
  if ( !wp_next_scheduled( $this->prefix( 'importexport_notify' ) ) ) {
1306
+ wp_schedule_single_event( Services::Request()->ts() + 15, $this->prefix( 'importexport_notify' ) );
1307
  }
1308
  }
1309
  }
1323
  * @return bool
1324
  */
1325
  public function isThisModulePage() {
1326
+ return $this->getCon()->isModulePage() && Services::Request()->query( 'page' ) == $this->getModSlug();
1327
  }
1328
 
1329
  /**
1330
  * @return bool
1331
  */
1332
  protected function isModuleOptionsRequest() {
1333
+ return Services::Request()->post( 'mod_slug' ) === $this->getModSlug();
1334
  }
1335
 
1336
  /**
1337
  * @return bool
1338
  */
1339
  protected function isWizardPage() {
1340
+ return ( Services::Request()->query( 'shield_action' ) == 'wizard' && $this->isThisModulePage() );
1341
  }
1342
 
1343
  /**
1426
  'nonce_field' => wp_nonce_field( $oCon->getPluginPrefix(), '_wpnonce', true, false ), //don't echo!
1427
  'form_action' => 'admin.php?page='.$this->getModSlug(),
1428
  'nOptionsPerRow' => 1,
1429
+ 'aPluginLabels' => $oCon->getLabels(),
1430
  'help_video' => array(
1431
  'auto_show' => $this->getIfAutoShowHelpVideo(),
1432
  'iframe_url' => $this->getHelpVideoUrl( $this->getHelpVideoId() ),
1561
  public function getUrl_Wizard( $sWizardSlug ) {
1562
  $aDef = $this->getWizardDefinition( $sWizardSlug );
1563
  if ( empty( $aDef[ 'min_user_permissions' ] ) ) { // i.e. no login/minimum perms
1564
+ $sUrl = Services::WpGeneral()->getHomeUrl();
1565
  }
1566
  else {
1567
+ $sUrl = Services::WpGeneral()->getAdminUrl( 'admin.php' );
1568
  }
1569
 
1570
  return add_query_arg(
1942
  * @return $this
1943
  */
1944
  protected function setOptAt( $sOpt, $nAt = null ) {
1945
+ $nAt = is_null( $nAt ) ? Services::Request()->ts() : max( 0, (int)$nAt );
1946
  return $this->setOpt( $sOpt, $nAt );
1947
  }
1948
 
 
 
 
 
 
 
 
 
1949
  /**
1950
  * @deprecated
1951
  * @return string
1953
  public function getVersion() {
1954
  return $this->getCon()->getVersion();
1955
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1956
  }
src/features/base_wpsf.php CHANGED
@@ -242,6 +242,7 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
242
  $oOpts = $this->getOptionsVo();
243
  return ( $oOpts->isModuleRunIfWhitelisted() || !$this->isVisitorWhitelisted() )
244
  && ( $oOpts->isModuleRunIfVerifiedBot() || !$this->isVerifiedBot() )
 
245
  && parent::isReadyToExecute();
246
  }
247
 
@@ -257,7 +258,6 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
257
  }
258
 
259
  /**
260
- * Only test for bots that we can actually verify based on IP, hostname
261
  * @return bool
262
  */
263
  public function isVerifiedBot() {
@@ -265,7 +265,7 @@ class ICWP_WPSF_FeatureHandler_BaseWpsf extends ICWP_WPSF_FeatureHandler_Base {
265
  $oSp = $this->loadServiceProviders();
266
 
267
  $sIp = Services::IP()->getRequestIp();
268
- $sAgent = (string)Services::Request()->server( 'HTTP_USER_AGENT' );
269
  if ( empty( $sAgent ) ) {
270
  $sAgent = 'Unknown';
271
  }
242
  $oOpts = $this->getOptionsVo();
243
  return ( $oOpts->isModuleRunIfWhitelisted() || !$this->isVisitorWhitelisted() )
244
  && ( $oOpts->isModuleRunIfVerifiedBot() || !$this->isVerifiedBot() )
245
+ && ( $oOpts->isModuleRunUnderWpCli() || !Services::WpGeneral()->isWpCli() )
246
  && parent::isReadyToExecute();
247
  }
248
 
258
  }
259
 
260
  /**
 
261
  * @return bool
262
  */
263
  public function isVerifiedBot() {
265
  $oSp = $this->loadServiceProviders();
266
 
267
  $sIp = Services::IP()->getRequestIp();
268
+ $sAgent = Services::Request()->getUserAgent();
269
  if ( empty( $sAgent ) ) {
270
  $sAgent = 'Unknown';
271
  }
src/features/comments_filter.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
 
 
 
3
  class ICWP_WPSF_FeatureHandler_CommentsFilter extends ICWP_WPSF_FeatureHandler_BaseWpsf {
4
 
5
  /**
@@ -45,7 +47,7 @@ class ICWP_WPSF_FeatureHandler_CommentsFilter extends ICWP_WPSF_FeatureHandler_B
45
  $oWpComments = $this->loadWpComments();
46
 
47
  // 1st are comments enabled on this post?
48
- $oPost = $this->loadWp()->getPostById( $this->getCommentItem( 'comment_post_ID' ) );
49
  return ( $oPost instanceof WP_Post ) && $oWpComments->isCommentsOpen( $oPost )
50
  && ( !$oWpComments->getIfAllowCommentsByPreviouslyApproved() || !$oWpComments->isAuthorApproved( $this->getCommentItem( 'comment_author_email' ) ) );
51
  }
1
  <?php
2
 
3
+ use FernleafSystems\Wordpress\Services\Services;
4
+
5
  class ICWP_WPSF_FeatureHandler_CommentsFilter extends ICWP_WPSF_FeatureHandler_BaseWpsf {
6
 
7
  /**
47
  $oWpComments = $this->loadWpComments();
48
 
49
  // 1st are comments enabled on this post?
50
+ $oPost = Services::WpPost()->getById( $this->getCommentItem( 'comment_post_ID' ) );
51
  return ( $oPost instanceof WP_Post ) && $oWpComments->isCommentsOpen( $oPost )
52
  && ( !$oWpComments->getIfAllowCommentsByPreviouslyApproved() || !$oWpComments->isAuthorApproved( $this->getCommentItem( 'comment_author_email' ) ) );
53
  }
src/features/hack_protect.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- use FernleafSystems\Wordpress\Plugin\Shield\Scans;
4
  use FernleafSystems\Wordpress\Services\Services;
5
 
6
  class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_BaseWpsf {
@@ -20,7 +20,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
20
  /**
21
  */
22
  public function handleModRequest() {
23
- $oReq = $this->loadRequest();
24
  switch ( $oReq->query( 'exec' ) && $this->getCon()->isPluginAdmin() ) {
25
  case 'scan_file_download':
26
  /** @var ICWP_WPSF_Processor_HackProtect $oPro */
@@ -90,7 +90,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
90
  * @return array
91
  */
92
  public function ajaxExec_PluginReinstall() {
93
- $oReq = $this->loadRequest();
94
  $bReinstall = (bool)$oReq->post( 'reinstall' );
95
  $bActivate = (bool)$oReq->post( 'activate' );
96
  $sFile = sanitize_text_field( wp_unslash( $oReq->post( 'file' ) ) );
@@ -172,10 +172,9 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
172
  $oSel = $oPro->getSubProScanner()
173
  ->getDbHandler()
174
  ->getQuerySelector();
175
- $nTotal = $oSel->filterByNotIgnored()
176
- ->filterByScan( $sScan )
177
- ->count();
178
- return $nTotal > 0;
179
  }
180
 
181
  /**
@@ -448,7 +447,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
448
  */
449
  public function isWpvulnPluginsHighlightEnabled() {
450
  $sOpt = $this->getWpvulnPluginsHighlightOption();
451
- return ( $sOpt != 'disabled' ) && $this->loadWpUsers()->isUserAdmin()
452
  && ( ( $sOpt != 'enabled_securityadmin' ) || $this->getCon()->isPluginAdmin() );
453
  }
454
 
@@ -456,12 +455,12 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
456
  * @return bool
457
  */
458
  public function canPtgWriteToDisk() {
459
- $nNow = $this->loadRequest()->ts();
460
  $bLastCheckExpired = ( $nNow - $this->getOpt( 'ptg_candiskwrite_at', 0 ) ) > DAY_IN_SECONDS;
461
 
462
  $bCanWrite = (bool)$this->getOpt( 'ptg_candiskwrite' ) && !$bLastCheckExpired;
463
  if ( !$bCanWrite ) {
464
- $oFS = $this->loadFS();
465
  $sDir = $this->getPtgSnapsBaseDir();
466
 
467
  if ( $sDir && $oFS->mkdir( $sDir ) ) {
@@ -602,7 +601,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
602
  * @return $this
603
  */
604
  public function setPtgLastBuildAt( $nTime = null ) {
605
- return $this->setOpt( 'ptg_last_build_at', is_null( $nTime ) ? $this->loadRequest()->ts() : $nTime );
606
  }
607
 
608
  /**
@@ -620,16 +619,23 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
620
  return !$this->isOpt( 'enabled_scan_apc', 'disabled' );
621
  }
622
 
 
 
 
 
 
 
 
623
  public function insertCustomJsVars_Admin() {
624
  parent::insertCustomJsVars_Admin();
625
 
626
- if ( $this->loadWp()->isCurrentPage( 'plugins.php' ) && $this->isPtgReinstallLinks() ) {
627
  wp_localize_script(
628
  $this->prefix( 'global-plugin' ),
629
  'icwp_wpsf_vars_hp',
630
  array(
631
  'ajax_plugin_reinstall' => $this->getAjaxActionData( 'plugin_reinstall' ),
632
- 'reinstallable' => $this->getReinstallablePlugins()
633
  )
634
  );
635
  wp_enqueue_script( 'jquery-ui-dialog' ); // jquery and jquery-ui should be dependencies, didn't check though...
@@ -637,20 +643,6 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
637
  }
638
  }
639
 
640
- /**
641
- * @return string[]
642
- */
643
- protected function getReinstallablePlugins() {
644
- $oWPP = $this->loadWpPlugins();
645
- $aP = $oWPP->getInstalledBaseFiles();
646
- foreach ( $aP as $nKey => $sPluginFile ) {
647
- if ( !$oWPP->isWpOrg( $sPluginFile ) ) {
648
- unset( $aP[ $nKey ] );
649
- }
650
- }
651
- return array_values( $aP );
652
- }
653
-
654
  /**
655
  * @param string $sSectionSlug
656
  * @return array
@@ -681,7 +673,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
681
  }
682
 
683
  if ( !is_null( $nTime ) ) {
684
- $nTime = ( $nTime > 0 ) ? $this->loadWp()->getTimeStampForDisplay( $nTime ) : _wpsf__( 'Never' );
685
  $aNotices[] = sprintf( _wpsf__( 'Last Scan Time: %s' ), $nTime );
686
  }
687
  return $aNotices;
@@ -692,26 +684,26 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
692
  */
693
  protected function ajaxExec_BuildTableScan() {
694
 
695
- switch ( $this->loadRequest()->post( 'fScan' ) ) {
696
 
697
  case 'apc':
698
- $oTableBuilder = new \FernleafSystems\Wordpress\Plugin\Shield\Tables\Build\ScanApc();
699
  break;
700
 
701
  case 'wcf':
702
- $oTableBuilder = new \FernleafSystems\Wordpress\Plugin\Shield\Tables\Build\ScanWcf();
703
  break;
704
 
705
  case 'ptg':
706
- $oTableBuilder = new \FernleafSystems\Wordpress\Plugin\Shield\Tables\Build\ScanPtg();
707
  break;
708
 
709
  case 'ufc':
710
- $oTableBuilder = new \FernleafSystems\Wordpress\Plugin\Shield\Tables\Build\ScanUfc();
711
  break;
712
 
713
  case 'wpv':
714
- $oTableBuilder = new \FernleafSystems\Wordpress\Plugin\Shield\Tables\Build\ScanWpv();
715
  break;
716
 
717
  default:
@@ -743,31 +735,9 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
743
  $aFormParams = $this->getAjaxFormParams();
744
 
745
  if ( !empty( $aFormParams ) ) {
746
- /** @var ICWP_WPSF_Processor_HackProtect $oP */
747
- $oP = $this->getProcessor();
748
- $oScanPro = $oP->getSubProScanner();
749
  foreach ( array_keys( $aFormParams ) as $sScan ) {
750
- switch ( $sScan ) {
751
- case 'ptg':
752
- $oTablePro = $oScanPro->getSubProcessorPtg();
753
- break;
754
-
755
- case 'ufc':
756
- $oTablePro = $oScanPro->getSubProcessorUfc();
757
- break;
758
-
759
- case 'wcf':
760
- $oTablePro = $oScanPro->getSubProcessorWcf();
761
- break;
762
-
763
- case 'wpv':
764
- $oTablePro = $oScanPro->getSubProcessorWpv();
765
- break;
766
-
767
- default:
768
- $oTablePro = null;
769
- break;
770
- }
771
 
772
  if ( !empty( $oTablePro ) && $oTablePro->isEnabled() ) {
773
  $oTablePro->doScan();
@@ -798,44 +768,16 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
798
  * @return array
799
  */
800
  private function ajaxExec_ScanItemAction( $sAction ) {
801
- /** @var ICWP_WPSF_Processor_HackProtect $oP */
802
- $oP = $this->getProcessor();
803
- $oReq = $this->loadRequest();
804
- $oScanPro = $oP->getSubProScanner();
805
 
806
  $bSuccess = false;
807
- $bReloadPage = false;
808
- switch ( $oReq->post( 'fScan' ) ) {
809
-
810
- case 'apc':
811
- $bReloadPage = true;
812
- $oTablePro = $oScanPro->getSubProcessorApc();
813
- break;
814
-
815
- case 'ptg':
816
- $bReloadPage = true;
817
- $oTablePro = $oScanPro->getSubProcessorPtg();
818
- break;
819
-
820
- case 'ufc':
821
- $oTablePro = $oScanPro->getSubProcessorUfc();
822
- break;
823
-
824
- case 'wcf':
825
- $oTablePro = $oScanPro->getSubProcessorWcf();
826
- break;
827
-
828
- case 'wpv':
829
- $oTablePro = $oScanPro->getSubProcessorWpv();
830
- break;
831
-
832
- default:
833
- $oTablePro = null;
834
- break;
835
- }
836
 
837
  $sItemId = $oReq->post( 'rid' );
838
  $aItemIds = $oReq->post( 'ids' );
 
 
 
 
839
  if ( empty( $oTablePro ) ) {
840
  $sMessage = _wpsf__( 'Unsupported scanner' );
841
  }
@@ -874,11 +816,43 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
874
 
875
  return array(
876
  'success' => $bSuccess,
877
- 'page_reload' => $bReloadPage,
878
  'message' => $sMessage,
879
  );
880
  }
881
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
882
  /**
883
  * @param string $sSection
884
  * @return array
@@ -997,6 +971,27 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
997
  }
998
  }
999
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1000
  $aNotices[ 'count' ] = count( $aNotices[ 'messages' ] );
1001
 
1002
  $aAllNotices[ 'scans' ] = $aNotices;
@@ -1119,7 +1114,7 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
1119
  */
1120
  public function getUrlManualScan() {
1121
  return add_query_arg(
1122
- [ 'subnav' => 'scans' ],
1123
  $this->getCon()->getModule( 'insights' )->getUrl_AdminPage()
1124
  );
1125
  }
@@ -1188,6 +1183,16 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
1188
  $sTitleShort = _wpsf__( 'Unrecognised Files Scanner' );
1189
  break;
1190
 
 
 
 
 
 
 
 
 
 
 
1191
  case 'section_pluginthemes_guard' :
1192
  $sTitle = _wpsf__( 'Plugins and Themes Guard' );
1193
  $sTitleShort = _wpsf__( 'Plugins/Themes Guard' );
@@ -1197,15 +1202,6 @@ class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_Base
1197
  );
1198
  break;
1199
 
1200
- case 'section_scan_apc' :
1201
- $sTitle = _wpsf__( 'Enable The Abandoned Plugin Scanner' );
1202
- $sTitleShort = _wpsf__( 'Abandoned Plugin Scanner' );
1203
- $aSummary = array(
1204
- // sprintf( '%s - %s', _wpsf__( 'Purpose' ), _wpsf__( 'Monitor for unrecognised changes to your system.' ) ),
1205
- // sprintf( '%s - %s', _wpsf__( 'Recommendation' ), _wpsf__( 'Enable these to prevent unauthorized changes to your WordPress site.' ) )
1206
- );
1207
- break;
1208
-
1209
  case 'section_integrity_checking' :
1210
  $sTitle = _wpsf__( 'Integrity Checks' );
1211
  $sTitleShort = _wpsf__( 'Integrity Checks' );
1
  <?php
2
 
3
+ use FernleafSystems\Wordpress\Plugin\Shield;
4
  use FernleafSystems\Wordpress\Services\Services;
5
 
6
  class ICWP_WPSF_FeatureHandler_HackProtect extends ICWP_WPSF_FeatureHandler_BaseWpsf {
20
  /**
21
  */
22
  public function handleModRequest() {
23
+ $oReq = Services::Request();
24
  switch ( $oReq->query( 'exec' ) && $this->getCon()->isPluginAdmin() ) {
25
  case 'scan_file_download':
26
  /** @var ICWP_WPSF_Processor_HackProtect $oPro */
90
  * @return array
91
  */
92
  public function ajaxExec_PluginReinstall() {
93
+ $oReq = Services::Request();
94
  $bReinstall = (bool)$oReq->post( 'reinstall' );
95
  $bActivate = (bool)$oReq->post( 'activate' );
96
  $sFile = sanitize_text_field( wp_unslash( $oReq->post( 'file' ) ) );
172
  $oSel = $oPro->getSubProScanner()
173
  ->getDbHandler()
174
  ->getQuerySelector();
175
+ return $oSel->filterByNotIgnored()
176
+ ->filterByScan( $sScan )
177
+ ->count() > 0;
 
178
  }
179
 
180
  /**
447
  */
448
  public function isWpvulnPluginsHighlightEnabled() {
449
  $sOpt = $this->getWpvulnPluginsHighlightOption();
450
+ return ( $sOpt != 'disabled' ) && Services::WpUsers()->isUserAdmin()
451
  && ( ( $sOpt != 'enabled_securityadmin' ) || $this->getCon()->isPluginAdmin() );
452
  }
453
 
455
  * @return bool
456
  */
457
  public function canPtgWriteToDisk() {
458
+ $nNow = Services::Request()->ts();
459
  $bLastCheckExpired = ( $nNow - $this->getOpt( 'ptg_candiskwrite_at', 0 ) ) > DAY_IN_SECONDS;
460
 
461
  $bCanWrite = (bool)$this->getOpt( 'ptg_candiskwrite' ) && !$bLastCheckExpired;
462
  if ( !$bCanWrite ) {
463
+ $oFS = Services::WpFs();
464
  $sDir = $this->getPtgSnapsBaseDir();
465
 
466
  if ( $sDir && $oFS->mkdir( $sDir ) ) {
601
  * @return $this
602
  */
603
  public function setPtgLastBuildAt( $nTime = null ) {
604
+ return $this->setOpt( 'ptg_last_build_at', is_null( $nTime ) ? Services::Request()->ts() : $nTime );
605
  }
606
 
607
  /**
619
  return !$this->isOpt( 'enabled_scan_apc', 'disabled' );
620
  }
621
 
622
+ /**
623
+ * @return bool
624
+ */
625
+ public function isApcSendEmail() {
626
+ return $this->isOpt( 'enabled_scan_apc', 'enabled_email' );
627
+ }
628
+
629
  public function insertCustomJsVars_Admin() {
630
  parent::insertCustomJsVars_Admin();
631
 
632
+ if ( Services::WpPost()->isCurrentPage( 'plugins.php' ) && $this->isPtgReinstallLinks() ) {
633
  wp_localize_script(
634
  $this->prefix( 'global-plugin' ),
635
  'icwp_wpsf_vars_hp',
636
  array(
637
  'ajax_plugin_reinstall' => $this->getAjaxActionData( 'plugin_reinstall' ),
638
+ 'reinstallable' => Services::WpPlugins()->getInstalledWpOrgPluginFiles()
639
  )
640
  );
641
  wp_enqueue_script( 'jquery-ui-dialog' ); // jquery and jquery-ui should be dependencies, didn't check though...
643
  }
644
  }
645
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
646
  /**
647
  * @param string $sSectionSlug
648
  * @return array
673
  }
674
 
675
  if ( !is_null( $nTime ) ) {
676
+ $nTime = ( $nTime > 0 ) ? Services::WpGeneral()->getTimeStampForDisplay( $nTime ) : _wpsf__( 'Never' );
677
  $aNotices[] = sprintf( _wpsf__( 'Last Scan Time: %s' ), $nTime );
678
  }
679
  return $aNotices;
684
  */
685
  protected function ajaxExec_BuildTableScan() {
686
 
687
+ switch ( Services::Request()->post( 'fScan' ) ) {
688
 
689
  case 'apc':
690
+ $oTableBuilder = new Shield\Tables\Build\ScanApc();
691
  break;
692
 
693
  case 'wcf':
694
+ $oTableBuilder = new Shield\Tables\Build\ScanWcf();
695
  break;
696
 
697
  case 'ptg':
698
+ $oTableBuilder = new Shield\Tables\Build\ScanPtg();
699
  break;
700
 
701
  case 'ufc':
702
+ $oTableBuilder = new Shield\Tables\Build\ScanUfc();
703
  break;
704
 
705
  case 'wpv':
706
+ $oTableBuilder = new Shield\Tables\Build\ScanWpv();
707
  break;
708
 
709
  default:
735
  $aFormParams = $this->getAjaxFormParams();
736
 
737
  if ( !empty( $aFormParams ) ) {
 
 
 
738
  foreach ( array_keys( $aFormParams ) as $sScan ) {
739
+
740
+ $oTablePro = $this->getScannerFromSlug( $sScan );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
741
 
742
  if ( !empty( $oTablePro ) && $oTablePro->isEnabled() ) {
743
  $oTablePro->doScan();
768
  * @return array
769
  */
770
  private function ajaxExec_ScanItemAction( $sAction ) {
771
+ $oReq = Services::Request();
 
 
 
772
 
773
  $bSuccess = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
774
 
775
  $sItemId = $oReq->post( 'rid' );
776
  $aItemIds = $oReq->post( 'ids' );
777
+ $sScannerSlug = $oReq->post( 'fScan' );
778
+
779
+ $oTablePro = $this->getScannerFromSlug( $sScannerSlug );
780
+
781
  if ( empty( $oTablePro ) ) {
782
  $sMessage = _wpsf__( 'Unsupported scanner' );
783
  }
816
 
817
  return array(
818
  'success' => $bSuccess,
819
+ 'page_reload' => in_array( $sScannerSlug, [ 'apc', 'ptg' ] ),
820
  'message' => $sMessage,
821
  );
822
  }
823
 
824
+ /**
825
+ * @param string $sSlug
826
+ * @return ICWP_WPSF_Processor_ScanBase|null
827
+ */
828
+ private function getScannerFromSlug( $sSlug ) {
829
+ /** @var ICWP_WPSF_Processor_HackProtect $oP */
830
+ $oP = $this->getProcessor();
831
+ $oScanPro = $oP->getSubProScanner();
832
+ switch ( $sSlug ) {
833
+ case 'apc':
834
+ $oScannerPro = $oScanPro->getSubProcessorApc();
835
+ break;
836
+ case 'ptg':
837
+ $oScannerPro = $oScanPro->getSubProcessorPtg();
838
+ break;
839
+ case 'ufc':
840
+ $oScannerPro = $oScanPro->getSubProcessorUfc();
841
+ break;
842
+ case 'wcf':
843
+ $oScannerPro = $oScanPro->getSubProcessorWcf();
844
+ break;
845
+ case 'wpv':
846
+ $oScannerPro = $oScanPro->getSubProcessorWpv();
847
+ break;
848
+ default:
849
+ $oScannerPro = null;
850
+ break;
851
+ }
852
+
853
+ return $oScannerPro;
854
+ }
855
+
856
  /**
857
  * @param string $sSection
858
  * @return array
971
  }
972
  }
973
 
974
+ {// Abandoned Plugins
975
+ if ( !$this->isApcEnabled() ) {
976
+ $aNotices[ 'messages' ][ 'apc' ] = array(
977
+ 'title' => 'Abandoned Plugins Scanner',
978
+ 'message' => _wpsf__( 'Abandoned Plugins Scanner is not enabled.' ),
979
+ 'href' => $this->getUrl_DirectLinkToSection( 'section_scan_apc' ),
980
+ 'action' => sprintf( 'Go To %s', _wpsf__( 'Options' ) ),
981
+ 'rec' => _wpsf__( 'Automatic detection of abandoned plugins is recommended.' )
982
+ );
983
+ }
984
+ else if ( $this->getScanHasProblem( 'apc' ) ) {
985
+ $aNotices[ 'messages' ][ 'apc' ] = array(
986
+ 'title' => 'Abandoned Plugins',
987
+ 'message' => _wpsf__( 'At least 1 plugin on your site is abandoned.' ),
988
+ 'href' => $this->getUrlManualScan(),
989
+ 'action' => _wpsf__( 'Run Scan' ),
990
+ 'rec' => _wpsf__( 'Plugins that have been abandoned represent a potential risk to your site.' )
991
+ );
992
+ }
993
+ }
994
+
995
  $aNotices[ 'count' ] = count( $aNotices[ 'messages' ] );
996
 
997
  $aAllNotices[ 'scans' ] = $aNotices;
1114
  */
1115
  public function getUrlManualScan() {
1116
  return add_query_arg(
1117
+ [ 'inav' => 'scans' ],
1118
  $this->getCon()->getModule( 'insights' )->getUrl_AdminPage()
1119
  );
1120
  }
1183
  $sTitleShort = _wpsf__( 'Unrecognised Files Scanner' );
1184
  break;
1185
 
1186
+ case 'section_scan_apc' :
1187
+ $sTitle = _wpsf__( 'Enable The Abandoned Plugin Scanner' );
1188
+ $sTitleShort = _wpsf__( 'Abandoned Plugin Scanner' );
1189
+ $aSummary = array(
1190
+ sprintf( '%s - %s', _wpsf__( 'Purpose' ),
1191
+ _wpsf__( 'Monitor your site for plugins that have been abandoned by their authors and are no longer maintained.' ) ),
1192
+ sprintf( '%s - %s', _wpsf__( 'Recommendation' ), _wpsf__( 'Enable this to alert you to your site running unmaintained code.' ) )
1193
+ );
1194
+ break;
1195
+
1196
  case 'section_pluginthemes_guard' :
1197
  $sTitle = _wpsf__( 'Plugins and Themes Guard' );
1198
  $sTitleShort = _wpsf__( 'Plugins/Themes Guard' );
1202
  );
1203
  break;
1204
 
 
 
 
 
 
 
 
 
 
1205
  case 'section_integrity_checking' :
1206
  $sTitle = _wpsf__( 'Integrity Checks' );
1207
  $sTitleShort = _wpsf__( 'Integrity Checks' );
src/features/insights.php CHANGED
@@ -9,7 +9,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
9
  */
10
  protected function displayModulePage( $aData = array() ) {
11
  $oCon = $this->getCon();
12
- $oReq = $this->loadRequest();
13
  $aSecNotices = $this->getNotices();
14
 
15
  $nNoticesCount = 0;
@@ -17,7 +17,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
17
  $nNoticesCount += isset( $aNoticeSection[ 'count' ] ) ? $aNoticeSection[ 'count' ] : 0;
18
  }
19
 
20
- $sSubNavSection = $this->loadRequest()->query( 'subnav' );
21
 
22
  /** @var ICWP_WPSF_FeatureHandler_Traffic $oTrafficMod */
23
  $oTrafficMod = $oCon->getModule( 'traffic' );
@@ -57,7 +57,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
57
  $bIsPro = $this->isPremium();
58
  $oCarbon = new \Carbon\Carbon();
59
  $nPluginName = $oCon->getHumanName();
60
- switch ( $sSubNavSection ) {
61
 
62
  case 'audit':
63
  $aData = array(
@@ -95,9 +95,11 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
95
  'auto_expire' => sprintf(
96
  'Black listed IPs auto-expire after: %s',
97
  sprintf( '<a href="%s" target="_blank">%s</a>',
98
- $oIpMod->getUrl_DirectLinkToOption( 'auto_expire' ), $oCarbon->setTimestamp( $oReq->ts() + $oIpMod->getAutoExpireTime() + 1 )
99
- ->diffForHumans( null, true )
100
- ) ),
 
 
101
  'title_whitelist' => _wpsf__( 'IP Whitelist' ),
102
  'title_blacklist' => _wpsf__( 'IP Blacklist' ),
103
  'summary_whitelist' => sprintf( _wpsf__( 'IP addresses that are never blocked by %s.' ), $nPluginName ),
@@ -179,7 +181,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
179
  case 'insights':
180
  case 'index':
181
  default:
182
- $sSubNavSection = 'insights';
183
  $aData = array(
184
  'vars' => array(
185
  'config_cards' => $this->getConfigCardsData(),
@@ -222,11 +224,16 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
222
  'notes' => _wpsf__( 'Notes' ),
223
  'importexport' => sprintf( '%s/%s', _wpsf__( 'Import' ), _wpsf__( 'Export' ) ),
224
  );
225
- array_walk( $aTopNav, function ( &$sName, $sKey ) use ( $sSubNavSection ) {
 
 
 
 
 
226
  $sName = array(
227
- 'href' => add_query_arg( [ 'subnav' => $sKey ], $this->getUrl_AdminPage() ),
228
  'name' => $sName,
229
- 'active' => $sKey === $sSubNavSection
230
  );
231
  } );
232
 
@@ -241,7 +248,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
241
  $this->getBaseDisplayData( false ),
242
  array(
243
  'classes' => array(
244
- 'page_container' => 'page-insights page-'.$sSubNavSection
245
  ),
246
  'flags' => array(
247
  'show_promo' => !$bIsPro
@@ -259,7 +266,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
259
  ),
260
  $aData
261
  );
262
- echo $this->renderTemplate( sprintf( '/wpadmin_pages/insights_new/%s/index.twig', $sSubNavSection ), $aData, true );
263
  }
264
 
265
  public function insertCustomJsVars_Admin() {
@@ -269,8 +276,8 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
269
 
270
  $oConn = $this->getCon();
271
  $aStdDeps = array( $this->prefix( 'plugin' ) );
272
- $sSubnav = $this->loadRequest()->query( 'subnav' );
273
- switch ( $sSubnav ) {
274
 
275
  case 'importexport':
276
 
@@ -305,7 +312,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
305
  wp_enqueue_script( $sUnique );
306
 
307
  $aStdDeps[] = $sUnique;
308
- if ( $sSubnav == 'scans' ) {
309
  $sAsset = 'shield-scans';
310
  $sUnique = $this->prefix( $sAsset );
311
  wp_register_script(
@@ -424,7 +431,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
424
  // If we didn't throw and exception, we got it.
425
  $nExpiresAt = $oSslService->getExpiresAt( $sHomeUrl );
426
  if ( $nExpiresAt > 0 ) {
427
- $nTimeLeft = ( $nExpiresAt - $this->loadRequest()->ts() );
428
  $bExpired = $nTimeLeft < 0;
429
  $nDaysLeft = $bExpired ? 0 : (int)round( $nTimeLeft/DAY_IN_SECONDS, 0, PHP_ROUND_HALF_DOWN );
430
 
@@ -600,8 +607,6 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
600
  $oConn = $this->getCon();
601
  /** @var ICWP_WPSF_FeatureHandler_UserManagement $oModUsers */
602
  $oModUsers = $oConn->getModule( 'user_management' );
603
- /** @var ICWP_WPSF_Processor_UserManagement $oProUsers */
604
- $oProUsers = $oModUsers->getProcessor();
605
  /** @var ICWP_WPSF_Processor_Statistics $oStats */
606
  $oStats = $oConn->getModule( 'statistics' )->getProcessor();
607
 
@@ -692,6 +697,7 @@ class ICWP_WPSF_FeatureHandler_Insights extends ICWP_WPSF_FeatureHandler_BaseWps
692
  return array(
693
  'insights_test_cron_last_run_at' => _wpsf__( 'Simple Test Cron' ),
694
  'insights_last_scan_ufc_at' => _wpsf__( 'Unrecognised Files Scan' ),
 
695
  'insights_last_scan_wcf_at' => _wpsf__( 'WordPress Core Files Scan' ),
696
  'insights_last_scan_ptg_at' => _wpsf__( 'Plugin/Themes Guard Scan' ),
697
  'insights_last_scan_wpv_at' => _wpsf__( 'Vulnerabilities Scan' ),
9
  */
10
  protected function displayModulePage( $aData = array() ) {
11
  $oCon = $this->getCon();
12
+ $oReq = Services::Request();
13
  $aSecNotices = $this->getNotices();
14
 
15
  $nNoticesCount = 0;
17
  $nNoticesCount += isset( $aNoticeSection[ 'count' ] ) ? $aNoticeSection[ 'count' ] : 0;
18
  }
19
 
20
+ $sNavSection = $oReq->query( 'inav' );
21
 
22
  /** @var ICWP_WPSF_FeatureHandler_Traffic $oTrafficMod */
23
  $oTrafficMod = $oCon->getModule( 'traffic' );
57
  $bIsPro = $this->isPremium();
58
  $oCarbon = new \Carbon\Carbon();
59
  $nPluginName = $oCon->getHumanName();
60
+ switch ( $sNavSection ) {
61
 
62
  case 'audit':
63
  $aData = array(
95
  'auto_expire' => sprintf(
96
  'Black listed IPs auto-expire after: %s',
97
  sprintf( '<a href="%s" target="_blank">%s</a>',
98
+ $oIpMod->getUrl_DirectLinkToOption( 'auto_expire' ),
99
+ $oCarbon->setTimestamp( $oReq->ts() + $oIpMod->getAutoExpireTime() + 1 )
100
+ ->diffForHumans( null, true )
101
+ )
102
+ ),
103
  'title_whitelist' => _wpsf__( 'IP Whitelist' ),
104
  'title_blacklist' => _wpsf__( 'IP Blacklist' ),
105
  'summary_whitelist' => sprintf( _wpsf__( 'IP addresses that are never blocked by %s.' ), $nPluginName ),
181
  case 'insights':
182
  case 'index':
183
  default:
184
+ $sNavSection = 'insights';
185
  $aData = array(
186
  'vars' => array(
187
  'config_cards' => $this->getConfigCardsData(),
224
  'notes' => _wpsf__( 'Notes' ),
225
  'importexport' => sprintf( '%s/%s', _wpsf__( 'Import' ), _wpsf__( 'Export' ) ),
226
  );
227
+ if ( $bIsPro ) {
228
+ unset( $aTopNav[ 'license' ] );
229
+ $aTopNav[ 'license' ] = _wpsf__( 'Pro' );
230
+ }
231
+
232
+ array_walk( $aTopNav, function ( &$sName, $sKey ) use ( $sNavSection ) {
233
  $sName = array(
234
+ 'href' => add_query_arg( [ 'inav' => $sKey ], $this->getUrl_AdminPage() ),
235
  'name' => $sName,
236
+ 'active' => $sKey === $sNavSection
237
  );
238
  } );
239
 
248
  $this->getBaseDisplayData( false ),
249
  array(
250
  'classes' => array(
251
+ 'page_container' => 'page-insights page-'.$sNavSection
252
  ),
253
  'flags' => array(
254
  'show_promo' => !$bIsPro
266
  ),
267
  $aData
268
  );
269
+ echo $this->renderTemplate( sprintf( '/wpadmin_pages/insights_new/%s/index.twig', $sNavSection ), $aData, true );
270
  }
271
 
272
  public function insertCustomJsVars_Admin() {
276
 
277
  $oConn = $this->getCon();
278
  $aStdDeps = array( $this->prefix( 'plugin' ) );
279
+ $sNav = Services::Request()->query( 'inav' );
280
+ switch ( $sNav ) {
281
 
282
  case 'importexport':
283
 
312
  wp_enqueue_script( $sUnique );
313
 
314
  $aStdDeps[] = $sUnique;
315
+ if ( $sNav == 'scans' ) {
316
  $sAsset = 'shield-scans';
317
  $sUnique = $this->prefix( $sAsset );
318
  wp_register_script(
431
  // If we didn't throw and exception, we got it.
432
  $nExpiresAt = $oSslService->getExpiresAt( $sHomeUrl );
433
  if ( $nExpiresAt > 0 ) {
434
+ $nTimeLeft = ( $nExpiresAt - Services::Request()->ts() );
435
  $bExpired = $nTimeLeft < 0;
436
  $nDaysLeft = $bExpired ? 0 : (int)round( $nTimeLeft/DAY_IN_SECONDS, 0, PHP_ROUND_HALF_DOWN );
437
 
607
  $oConn = $this->getCon();
608
  /** @var ICWP_WPSF_FeatureHandler_UserManagement $oModUsers */
609
  $oModUsers = $oConn->getModule( 'user_management' );
 
 
610
  /** @var ICWP_WPSF_Processor_Statistics $oStats */
611
  $oStats = $oConn->getModule( 'statistics' )->getProcessor();
612
 
697
  return array(
698
  'insights_test_cron_last_run_at' => _wpsf__( 'Simple Test Cron' ),
699
  'insights_last_scan_ufc_at' => _wpsf__( 'Unrecognised Files Scan' ),
700
+ 'insights_last_scan_apc_at' => _wpsf__( 'Abandoned Plugins Scan' ),
701
  'insights_last_scan_wcf_at' => _wpsf__( 'WordPress Core Files Scan' ),
702
  'insights_last_scan_ptg_at' => _wpsf__( 'Plugin/Themes Guard Scan' ),
703
  'insights_last_scan_wpv_at' => _wpsf__( 'Vulnerabilities Scan' ),
src/features/ips.php CHANGED
@@ -60,7 +60,7 @@ class ICWP_WPSF_FeatureHandler_Ips extends ICWP_WPSF_FeatureHandler_BaseWpsf {
60
  public function handleAuthAjax( $aAjaxResponse ) {
61
 
62
  if ( empty( $aAjaxResponse ) ) {
63
- switch ( $this->loadRequest()->request( 'exec' ) ) {
64
 
65
  case 'ip_insert':
66
  $aAjaxResponse = $this->ajaxExec_AddIp();
@@ -82,12 +82,11 @@ class ICWP_WPSF_FeatureHandler_Ips extends ICWP_WPSF_FeatureHandler_BaseWpsf {
82
  }
83
 
84
  protected function ajaxExec_IpDelete() {
85
- $oReq = $this->loadRequest();
86
  /** @var ICWP_WPSF_Processor_Ips $oProcessor */
87
  $oProcessor = $this->getProcessor();
88
 
89
  $bSuccess = false;
90
- $nId = $oReq->post( 'rid', -1 );
91
  if ( !is_numeric( $nId ) || $nId < 0 ) {
92
  $sMessage = _wpsf__( "Invalid entry selected" );
93
  }
@@ -217,7 +216,7 @@ class ICWP_WPSF_FeatureHandler_Ips extends ICWP_WPSF_FeatureHandler_BaseWpsf {
217
  /** @var ICWP_WPSF_FeatureHandler_Plugin $oPluginMod */
218
  $oPluginMod = $this->getCon()->getModule( 'plugin' );
219
  return [
220
- $this->loadRequest()->server( 'SERVER_ADDR' ),
221
  $oPluginMod->getMyServerIp()
222
  ];
223
  }
60
  public function handleAuthAjax( $aAjaxResponse ) {
61
 
62
  if ( empty( $aAjaxResponse ) ) {
63
+ switch ( Services::Request()->request( 'exec' ) ) {
64
 
65
  case 'ip_insert':
66
  $aAjaxResponse = $this->ajaxExec_AddIp();
82
  }
83
 
84
  protected function ajaxExec_IpDelete() {
 
85
  /** @var ICWP_WPSF_Processor_Ips $oProcessor */
86
  $oProcessor = $this->getProcessor();
87
 
88
  $bSuccess = false;
89
+ $nId = Services::Request()->post( 'rid', -1 );
90
  if ( !is_numeric( $nId ) || $nId < 0 ) {
91
  $sMessage = _wpsf__( "Invalid entry selected" );
92
  }
216
  /** @var ICWP_WPSF_FeatureHandler_Plugin $oPluginMod */
217
  $oPluginMod = $this->getCon()->getModule( 'plugin' );
218
  return [
219
+ Services::Request()->getServerAddress(),
220
  $oPluginMod->getMyServerIp()
221
  ];
222
  }
src/features/license.php CHANGED
@@ -7,9 +7,9 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
7
 
8
  protected function doPostConstruction() {
9
  if ( $this->isThisModulePage() ) {
10
- $this->loadWp()->doRedirect(
11
  $this->getCon()->getModule( 'insights' )->getUrl_AdminPage(),
12
- [ 'subnav' => 'license' ]
13
  );
14
  }
15
  }
@@ -34,7 +34,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
34
  * @return array
35
  */
36
  protected function getDisplayStrings() {
37
- return $this->loadDP()->mergeArraysRecursive(
38
  parent::getDisplayStrings(),
39
  array(
40
  'product_name' => _wpsf__( 'Name' ),
@@ -86,7 +86,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
86
  public function handleAuthAjax( $aAjaxResponse ) {
87
 
88
  if ( empty( $aAjaxResponse ) ) {
89
- switch ( $this->loadRequest()->request( 'exec' ) ) {
90
 
91
  case 'license_handling':
92
  $aAjaxResponse = $this->ajaxExec_LicenseHandling();
@@ -106,11 +106,11 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
106
  /**
107
  * @return array
108
  */
109
- protected function ajaxExec_LicenseHandling() {
110
  $bSuccess = false;
111
  $sMessage = 'Unsupported license action';
112
 
113
- $sLicenseAction = $this->loadRequest()->post( 'license-action' );
114
 
115
  $nCheckInterval = $this->getLicenseNotCheckedForInterval();
116
  if ( $nCheckInterval < 20 ) {
@@ -147,44 +147,39 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
147
  /**
148
  * @return array
149
  */
150
- protected function ajaxExec_ConnectionDebug() {
151
  $bSuccess = false;
152
 
153
- $sStoreUrl = add_query_arg(
154
- array( 'license_ping' => 'Y' ),
155
- $this->getLicenseStoreUrl()
156
- );
157
-
158
- $mResponse = $this->loadFS()->requestUrl(
159
- $sStoreUrl,
160
- array(
161
- 'method' => 'POST',
162
- 'body' => array( 'ping' => 'pong' )
163
- ),
164
- true
165
- );
166
-
167
- if ( is_wp_error( $mResponse ) ) {
168
- $sResult = $mResponse->get_error_message();
169
  }
170
- else if ( is_array( $mResponse ) && !empty( $mResponse[ 'body' ] ) ) {
171
- $aResult = @json_decode( $mResponse[ 'body' ], true );
172
  if ( isset( $aResult[ 'success' ] ) && $aResult[ 'success' ] ) {
173
  $bSuccess = true;
174
  $sResult = 'Successful - no problems detected communicating with license server.';
175
  }
176
  else {
177
- $sResult = 'Unknown failure due to unexpected response';
178
  }
179
  }
180
  else {
181
- $sResult = 'Unknown error as we could not get a response back from the server';
182
  }
183
 
184
- return array(
185
  'success' => $bSuccess,
186
- 'message' => esc_html( esc_js( $sResult ) )
187
- );
188
  }
189
 
190
  /**
@@ -255,7 +250,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
255
  }
256
  }
257
 
258
- $oCurrent->setLastRequestAt( $this->loadRequest()->ts() );
259
  $this->setLicenseData( $oCurrent )
260
  ->savePluginOptions();
261
  }
@@ -278,8 +273,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
278
  * @return bool
279
  */
280
  private function canLicenseCheck() {
281
- $sShieldAction = $this->loadRequest()->query( 'shield_action' );
282
- return !in_array( $sShieldAction, array( 'keyless_handshake', 'license_check' ) )
283
  && $this->canLicenseCheck_FileFlag();
284
  }
285
 
@@ -287,17 +281,17 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
287
  * @return bool
288
  */
289
  private function canLicenseCheck_FileFlag() {
290
- $oFs = $this->loadFS();
291
  $sFileFlag = $this->getCon()->getPath_Flags( 'license_check' );
292
  $nMtime = $oFs->exists( $sFileFlag ) ? $oFs->getModifiedTime( $sFileFlag ) : 0;
293
- return ( $this->loadRequest()->ts() - $nMtime ) > MINUTE_IN_SECONDS;
294
  }
295
 
296
  /**
297
  * @return $this
298
  */
299
  private function touchLicenseCheckFileFlag() {
300
- $this->loadFS()->touch( $this->getCon()->getPath_Flags( 'license_check' ) );
301
  return $this;
302
  }
303
 
@@ -307,7 +301,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
307
  protected function isLicenseMaybeExpiring() {
308
  $bNearly = $this->isLicenseActive() &&
309
  (
310
- abs( $this->loadRequest()->ts() - $this->loadLicense()->getExpiresAt() )
311
  < ( DAY_IN_SECONDS/2 )
312
  );
313
  return $bNearly;
@@ -327,8 +321,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
327
  /**
328
  */
329
  protected function sendLicenseWarningEmail() {
330
- $nNow = $this->loadRequest()->ts();
331
- $bCanSend = $nNow - $this->getOpt( 'last_warning_email_sent_at' ) > DAY_IN_SECONDS;
332
 
333
  if ( $bCanSend ) {
334
  $this->setOptAt( 'last_warning_email_sent_at' )->savePluginOptions();
@@ -349,7 +342,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
349
  /**
350
  */
351
  private function sendLicenseDeactivatedEmail() {
352
- $nNow = $this->loadRequest()->ts();
353
 
354
  if ( ( $nNow - $this->getOpt( 'last_deactivated_email_sent_at' ) ) > DAY_IN_SECONDS ) {
355
  $this->setOptAt( 'last_deactivated_email_sent_at' )->savePluginOptions();
@@ -375,7 +368,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
375
  $sPass = wp_generate_password( 16 );
376
 
377
  $this->setKeylessRequestAt()
378
- ->setKeylessRequestHash( sha1( $sPass.$this->loadWp()->getHomeUrl() ) )
379
  ->savePluginOptions();
380
 
381
  $oLicense = $this->loadEdd()
@@ -468,7 +461,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
468
  * @return int
469
  */
470
  private function getLicenseNotCheckedForInterval() {
471
- return ( $this->loadRequest()->ts() - $this->getLicenseLastCheckedAt() );
472
  }
473
 
474
  /**
@@ -514,7 +507,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
514
  * @return bool
515
  */
516
  protected function isLastVerifiedExpired() {
517
- return ( $this->loadRequest()->ts() - $this->loadLicense()->getLastVerifiedAt() )
518
  > $this->getDef( 'lic_verify_expire_days' )*DAY_IN_SECONDS;
519
  }
520
 
@@ -524,7 +517,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
524
  protected function isLastVerifiedGraceExpired() {
525
  $nGracePeriod = ( $this->getDef( 'lic_verify_expire_days' ) + $this->getDef( 'lic_verify_expire_grace_days' ) )
526
  *DAY_IN_SECONDS;
527
- return ( $this->loadRequest()->ts() - $this->loadLicense()->getLastVerifiedAt() ) > $nGracePeriod;
528
  }
529
 
530
  /**
@@ -612,7 +605,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
612
  * @return bool
613
  */
614
  public function isKeylessHandshakeExpired() {
615
- return ( $this->loadRequest()->ts() - $this->getKeylessRequestAt() )
616
  > $this->getDef( 'keyless_handshake_expire' );
617
  }
618
 
@@ -629,7 +622,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
629
  * @return $this
630
  */
631
  public function setKeylessRequestAt( $nTime = null ) {
632
- $nTime = is_numeric( $nTime ) ? $nTime : $this->loadRequest()->ts();
633
  return $this->setOpt( 'keyless_request_at', $nTime );
634
  }
635
 
@@ -641,7 +634,7 @@ class ICWP_WPSF_FeatureHandler_License extends ICWP_WPSF_FeatureHandler_BaseWpsf
641
  }
642
 
643
  public function buildInsightsVars() {
644
- $oWp = $this->loadWp();
645
  $oCarbon = new \Carbon\Carbon();
646
 
647
  $oCurrent = $this->loadLicense();
7
 
8
  protected function doPostConstruction() {
9
  if ( $this->isThisModulePage() ) {
10
+ Services::Response()->redirect(
11
  $this->getCon()->getModule( 'insights' )->getUrl_AdminPage(),
12
+ [ 'inav' => 'license' ]
13
  );
14
  }
15
  }
34
  * @return array
35
  */
36
  protected function getDisplayStrings() {
37
+ return Services::DataManipulation()->mergeArraysRecursive(
38
  parent::getDisplayStrings(),
39
  array(
40
  'product_name' => _wpsf__( 'Name' ),
86
  public function handleAuthAjax( $aAjaxResponse ) {
87
 
88
  if ( empty( $aAjaxResponse ) ) {
89
+ switch ( Services::Request()->request( 'exec' ) ) {
90
 
91
  case 'license_handling':
92
  $aAjaxResponse = $this->ajaxExec_LicenseHandling();
106
  /**
107
  * @return array
108
  */
109
+ private function ajaxExec_LicenseHandling() {
110
  $bSuccess = false;
111
  $sMessage = 'Unsupported license action';
112
 
113
+ $sLicenseAction = Services::Request()->post( 'license-action' );
114
 
115
  $nCheckInterval = $this->getLicenseNotCheckedForInterval();
116
  if ( $nCheckInterval < 20 ) {
147
  /**
148
  * @return array
149
  */
150
+ private function ajaxExec_ConnectionDebug() {
151
  $bSuccess = false;
152
 
153
+ $oHttpReq = Services::HttpRequest()
154
+ ->request(
155
+ add_query_arg( [ 'license_ping' => 'Y' ], $this->getLicenseStoreUrl() ),
156
+ [
157
+ 'body' => [ 'ping' => 'pong' ]
158
+ ],
159
+ 'POST'
160
+ );
161
+
162
+ if ( !$oHttpReq->isSuccess() ) {
163
+ $sResult = implode( '; ', $oHttpReq->lastError->get_error_messages() );
 
 
 
 
 
164
  }
165
+ else if ( !empty( $oHttpReq->lastResponse->body ) ) {
166
+ $aResult = @json_decode( $oHttpReq->lastResponse->body, true );
167
  if ( isset( $aResult[ 'success' ] ) && $aResult[ 'success' ] ) {
168
  $bSuccess = true;
169
  $sResult = 'Successful - no problems detected communicating with license server.';
170
  }
171
  else {
172
+ $sResult = 'Unknown failure due to unexpected response.';
173
  }
174
  }
175
  else {
176
+ $sResult = 'Unknown error as we could not get a response back from the server.';
177
  }
178
 
179
+ return [
180
  'success' => $bSuccess,
181
+ 'message' => $sResult
182
+ ];
183
  }
184
 
185
  /**
250
  }
251
  }
252
 
253
+ $oCurrent->setLastRequestAt( Services::Request()->ts() );
254
  $this->setLicenseData( $oCurrent )
255
  ->savePluginOptions();
256
  }
273
  * @return bool
274
  */
275
  private function canLicenseCheck() {
276
+ return !in_array( Services::Request()->query( 'shield_action' ), [ 'keyless_handshake', 'license_check' ] )
 
277
  && $this->canLicenseCheck_FileFlag();
278
  }
279
 
281
  * @return bool
282
  */
283
  private function canLicenseCheck_FileFlag() {
284
+ $oFs = Services::WpFs();
285
  $sFileFlag = $this->getCon()->getPath_Flags( 'license_check' );
286
  $nMtime = $oFs->exists( $sFileFlag ) ? $oFs->getModifiedTime( $sFileFlag ) : 0;
287
+ return ( Services::Request()->ts() - $nMtime ) > MINUTE_IN_SECONDS;
288
  }
289
 
290
  /**
291
  * @return $this
292
  */
293
  private function touchLicenseCheckFileFlag() {
294
+ Services::WpFs()->touch( $this->getCon()->getPath_Flags( 'license_check' ) );
295
  return $this;
296
  }
297
 
301
  protected function isLicenseMaybeExpiring() {
302
  $bNearly = $this->isLicenseActive() &&
303
  (
304
+ abs( Services::Request()->ts() - $this->loadLicense()->getExpiresAt() )
305
  < ( DAY_IN_SECONDS/2 )
306
  );
307
  return $bNearly;
321
  /**
322
  */
323
  protected function sendLicenseWarningEmail() {
324
+ $bCanSend = Services::Request()->ts() - $this->getOpt( 'last_warning_email_sent_at' ) > DAY_IN_SECONDS;
 
325
 
326
  if ( $bCanSend ) {
327
  $this->setOptAt( 'last_warning_email_sent_at' )->savePluginOptions();
342
  /**
343
  */
344
  private function sendLicenseDeactivatedEmail() {
345
+ $nNow = Services::Request()->ts();
346
 
347
  if ( ( $nNow - $this->getOpt( 'last_deactivated_email_sent_at' ) ) > DAY_IN_SECONDS ) {
348
  $this->setOptAt( 'last_deactivated_email_sent_at' )->savePluginOptions();
368
  $sPass = wp_generate_password( 16 );
369
 
370
  $this->setKeylessRequestAt()
371
+ ->setKeylessRequestHash( sha1( $sPass.Services::WpGeneral()->getHomeUrl() ) )
372
  ->savePluginOptions();
373
 
374
  $oLicense = $this->loadEdd()
461
  * @return int
462
  */
463
  private function getLicenseNotCheckedForInterval() {
464
+ return ( Services::Request()->ts() - $this->getLicenseLastCheckedAt() );
465
  }
466
 
467
  /**
507
  * @return bool
508
  */
509
  protected function isLastVerifiedExpired() {
510
+ return ( Services::Request()->ts() - $this->loadLicense()->getLastVerifiedAt() )
511
  > $this->getDef( 'lic_verify_expire_days' )*DAY_IN_SECONDS;
512
  }
513
 
517
  protected function isLastVerifiedGraceExpired() {
518
  $nGracePeriod = ( $this->getDef( 'lic_verify_expire_days' ) + $this->getDef( 'lic_verify_expire_grace_days' ) )
519
  *DAY_IN_SECONDS;
520
+ return ( Services::Request()->ts() - $this->loadLicense()->getLastVerifiedAt() ) > $nGracePeriod;
521
  }
522
 
523
  /**
605
  * @return bool
606
  */
607
  public function isKeylessHandshakeExpired() {
608
+ return ( Services::Request()->ts() - $this->getKeylessRequestAt() )
609
  > $this->getDef( 'keyless_handshake_expire' );
610
  }
611
 
622
  * @return $this
623
  */
624
  public function setKeylessRequestAt( $nTime = null ) {
625
+ $nTime = is_numeric( $nTime ) ? $nTime : Services::Request()->ts();
626
  return $this->setOpt( 'keyless_request_at', $nTime );
627
  }
628
 
634
  }
635
 
636
  public function buildInsightsVars() {
637
+ $oWp = Services::WpGeneral();
638
  $oCarbon = new \Carbon\Carbon();
639
 
640
  $oCurrent = $this->loadLicense();
src/features/lockdown.php CHANGED
@@ -71,7 +71,8 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_BaseWps
71
  );
72
 
73
  { //edit plugins
74
- if ( current_user_can( 'edit_plugins' ) ) { //assumes current user is admin
 
75
  $aNotices[ 'messages' ][ 'disallow_file_edit' ] = array(
76
  'title' => 'Code Editor',
77
  'message' => _wpsf__( 'Direct editing of plugin/theme files is permitted.' ),
@@ -106,7 +107,7 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_BaseWps
106
  $aThis[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
107
  }
108
  else {
109
- $bEditingDisabled = !current_user_can( 'edit_plugins' );
110
  $aThis[ 'key_opts' ][ 'editing' ] = array(
111
  'name' => _wpsf__( 'WP File Editing' ),
112
  'enabled' => $bEditingDisabled,
@@ -278,7 +279,7 @@ class ICWP_WPSF_FeatureHandler_Lockdown extends ICWP_WPSF_FeatureHandler_BaseWps
278
  }
279
 
280
  protected function getCanDoAuthSalts() {
281
- $oWpFs = $this->loadFS();
282
 
283
  if ( !$oWpFs->getCanWpRemoteGet() ) {
284
  return false;
71
  );
72
 
73
  { //edit plugins
74
+ $bEditingDisabled = $this->isOptFileEditingDisabled() || !current_user_can( 'edit_plugins' );
75
+ if ( !$bEditingDisabled ) { //assumes current user is admin
76
  $aNotices[ 'messages' ][ 'disallow_file_edit' ] = array(
77
  'title' => 'Code Editor',
78
  'message' => _wpsf__( 'Direct editing of plugin/theme files is permitted.' ),
107
  $aThis[ 'key_opts' ][ 'mod' ] = $this->getModDisabledInsight();
108
  }
109
  else {
110
+ $bEditingDisabled = $this->isOptFileEditingDisabled() || !current_user_can( 'edit_plugins' );
111
  $aThis[ 'key_opts' ][ 'editing' ] = array(
112
  'name' => _wpsf__( 'WP File Editing' ),
113
  'enabled' => $bEditingDisabled,
279
  }
280
 
281
  protected function getCanDoAuthSalts() {
282
+ $oWpFs = Services::WpFs();
283
 
284
  if ( !$oWpFs->getCanWpRemoteGet() ) {
285
  return false;
src/features/login_protect.php CHANGED
@@ -46,7 +46,7 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
46
  /**
47
  */
48
  public function handleModRequest() {
49
- switch ( $this->loadRequest()->query( 'exec' ) ) {
50
  case 'email_send_verify':
51
  $this->processEmailSendVerify();
52
  break;
@@ -78,7 +78,7 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
78
  $sMessage = _wpsf__( 'Email verification could not be completed.' );
79
  }
80
  $this->setFlashAdminNotice( $sMessage, !$bSuccess );
81
- $this->loadWp()->doRedirect( $this->getUrl_AdminPage() );
82
  }
83
 
84
  /**
@@ -88,7 +88,7 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
88
  */
89
  public function sendEmailVerifyCanSend( $sEmail = null, $bSendAsLink = true ) {
90
 
91
- if ( !$this->loadDP()->validEmail( $sEmail ) ) {
92
  $sEmail = get_bloginfo( 'admin_email' );
93
  }
94
 
@@ -238,14 +238,14 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
238
  * @return bool
239
  */
240
  public function canUserMfaSkip( $oUser ) {
241
-
242
  if ( $this->getMfaSkipEnabled() ) {
243
  $aHashes = $this->getMfaLoginHashes( $oUser );
244
  $nSkipTime = $this->getMfaSkip()*DAY_IN_SECONDS;
245
 
246
- $sHash = md5( $this->loadRequest()->getUserAgent() );
247
  $bCanSkip = isset( $aHashes[ $sHash ] )
248
- && ( (int)$aHashes[ $sHash ] + $nSkipTime ) > $this->loadRequest()->ts();
249
  }
250
  else if ( $this->getIfSupport3rdParty() && class_exists( 'WC_Social_Login' ) ) {
251
  // custom support for WooCommerce Social login
@@ -261,18 +261,18 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
261
  */
262
  $bCanSkip = apply_filters(
263
  'odp-shield-2fa_skip',
264
- strpos( $this->loadRequest()->server( 'HTTP_REFERER' ), 'https://app.icontrolwp.com/' ) === 0
265
  );
266
  }
267
  return $bCanSkip;
268
  }
269
 
270
  /**
271
- * @param WP_User $oUser
272
  * @return $this
273
  */
274
  public function addMfaLoginHash( $oUser ) {
275
- $oReq = $this->loadRequest();
276
  $aHashes = $this->getMfaLoginHashes( $oUser );
277
  $aHashes[ md5( $oReq->getUserAgent() ) ] = $oReq->ts();
278
  $this->getCon()->getCurrentUserMeta()->hash_loginmfa = $aHashes;
@@ -417,7 +417,7 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
417
  public function setIfCanSendEmail( $bCan ) {
418
  $nCurrentDateAt = $this->getCanSendEmailVerifiedAt();
419
  if ( $bCan ) {
420
- $nDateAt = ( $nCurrentDateAt <= 0 ) ? $this->loadRequest()->ts() : $nCurrentDateAt;
421
  }
422
  else {
423
  $nDateAt = 0;
@@ -552,7 +552,7 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
552
  public function handleAuthAjax( $aAjaxResponse ) {
553
 
554
  if ( empty( $aAjaxResponse ) ) {
555
- switch ( $this->loadRequest()->request( 'exec' ) ) {
556
 
557
  case 'gen_backup_codes':
558
  $aAjaxResponse = $this->ajaxExec_GenBackupCodes();
@@ -585,7 +585,7 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
585
  $oPro = $this->loadProcessor();
586
  $sPass = $oPro->getProcessorLoginIntent()
587
  ->getProcessorBackupCodes()
588
- ->resetSecret( $this->loadWpUsers()->getCurrentWpUser() );
589
 
590
  foreach ( array( 20, 15, 10, 5 ) as $nPos ) {
591
  $sPass = substr_replace( $sPass, '-', $nPos, 0 );
@@ -666,7 +666,7 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
666
  $oPro = $this->loadProcessor();
667
  $oPro->getProcessorLoginIntent()
668
  ->getProcessorBackupCodes()
669
- ->deleteSecret( $this->loadWpUsers()->getCurrentWpUser() );
670
  $this->setFlashAdminNotice( _wpsf__( 'Multi-factor login backup code has been removed from your profile' ) );
671
  return array(
672
  'success' => true
@@ -823,7 +823,6 @@ class ICWP_WPSF_FeatureHandler_LoginProtect extends ICWP_WPSF_FeatureHandler_Bas
823
 
824
  case 'section_rename_wplogin' :
825
  $sTitle = _wpsf__( 'Hide WordPress Login Page' );
826
- $sTitleShort = sprintf( _wpsf__( 'Rename "%s"' ), 'wp-login.php' );
827
  $sTitleShort = _wpsf__( 'Hide Login Page' );
828
  $aSummary = array(
829
  sprintf( '%s - %s', _wpsf__( 'Purpose' ), _wpsf__( 'To hide your wp-login.php page from brute force attacks and hacking attempts - if your login page cannot be found, no-one can login.' ) ),
46
  /**
47
  */
48
  public function handleModRequest() {
49
+ switch ( Services::Request()->query( 'exec' ) ) {
50
  case 'email_send_verify':
51
  $this->processEmailSendVerify();
52
  break;
78
  $sMessage = _wpsf__( 'Email verification could not be completed.' );
79
  }
80
  $this->setFlashAdminNotice( $sMessage, !$bSuccess );
81
+ Services::Response()->redirect( $this->getUrl_AdminPage() );
82
  }
83
 
84
  /**
88
  */
89
  public function sendEmailVerifyCanSend( $sEmail = null, $bSendAsLink = true ) {
90
 
91
+ if ( !Services::Data()->validEmail( $sEmail ) ) {
92
  $sEmail = get_bloginfo( 'admin_email' );
93
  }
94
 
238
  * @return bool
239
  */
240
  public function canUserMfaSkip( $oUser ) {
241
+ $oReq = Services::Request();
242
  if ( $this->getMfaSkipEnabled() ) {
243
  $aHashes = $this->getMfaLoginHashes( $oUser );
244
  $nSkipTime = $this->getMfaSkip()*DAY_IN_SECONDS;
245
 
246
+ $sHash = md5( $oReq->getUserAgent() );
247
  $bCanSkip = isset( $aHashes[ $sHash ] )
248
+ && ( (int)$aHashes[ $sHash ] + $nSkipTime ) > $oReq->ts();
249
  }
250
  else if ( $this->getIfSupport3rdParty() && class_exists( 'WC_Social_Login' ) ) {
251
  // custom support for WooCommerce Social login
261
  */
262
  $bCanSkip = apply_filters(
263
  'odp-shield-2fa_skip',
264
+ strpos( $oReq->server( 'HTTP_REFERER' ), 'https://app.icontrolwp.com/' ) === 0
265
  );
266
  }
267
  return $bCanSkip;
268
  }
269
 
270
  /**
271
+ * @param \WP_User $oUser
272
  * @return $this
273
  */
274
  public function addMfaLoginHash( $oUser ) {
275
+ $oReq = Services::Request();
276
  $aHashes = $this->getMfaLoginHashes( $oUser );
277
  $aHashes[ md5( $oReq->getUserAgent() ) ] = $oReq->ts();
278
  $this->getCon()->getCurrentUserMeta()->hash_loginmfa = $aHashes;
417
  public function setIfCanSendEmail( $bCan ) {
418
  $nCurrentDateAt = $this->getCanSendEmailVerifiedAt();
419
  if ( $bCan ) {
420
+ $nDateAt = ( $nCurrentDateAt <= 0 ) ? Services::Request()->ts() : $nCurrentDateAt;
421
  }
422
  else {
423
  $nDateAt = 0;
552
  public function handleAuthAjax( $aAjaxResponse ) {
553
 
554
  if ( empty( $aAjaxResponse ) ) {
555
+ switch ( Services::Request()->request( 'exec' ) ) {
556
 
557
  case 'gen_backup_codes':
558
  $aAjaxResponse = $this->ajaxExec_GenBackupCodes();
585
  $oPro = $this->loadProcessor();
586
  $sPass = $oPro->getProcessorLoginIntent()
587
  ->getProcessorBackupCodes()
588
+ ->resetSecret( Services::WpUsers()->getCurrentWpUser() );
589
 
590
  foreach ( array( 20, 15, 10, 5 ) as $nPos ) {
591
  $sPass = substr_replace( $sPass, '-', $nPos, 0 );
666
  $oPro = $this->loadProcessor();
667
  $oPro->getProcessorLoginIntent()
668
  ->getProcessorBackupCodes()
669
+ ->deleteSecret( Services::WpUsers()->getCurrentWpUser() );
670
  $this->setFlashAdminNotice( _wpsf__( 'Multi-factor login backup code has been removed from your profile' ) );
671
  return array(
672
  'success' => true
823
 
824
  case 'section_rename_wplogin' :
825
  $sTitle = _wpsf__( 'Hide WordPress Login Page' );
 
826
  $sTitleShort = _wpsf__( 'Hide Login Page' );
827
  $aSummary = array(
828
  sprintf( '%s - %s', _wpsf__( 'Purpose' ), _wpsf__( 'To hide your wp-login.php page from brute force attacks and hacking attempts - if your login page cannot be found, no-one can login.' ) ),
src/features/mousetrap.php ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use FernleafSystems\Wordpress\Services\Services;
4
+
5
+ class ICWP_WPSF_FeatureHandler_Mousetrap extends ICWP_WPSF_FeatureHandler_BaseWpsf {
6
+
7
+ protected function doPostConstruction() {
8
+ }
9
+
10
+ /**
11
+ * @return bool
12
+ */
13
+ public function isEnabled404() {
14
+ return $this->isSelectOptionEnabled( '404_detect' );
15
+ }
16
+
17
+ /**
18
+ * @return bool
19
+ */
20
+ public function isEnabledFakeWebCrawler() {
21
+ return $this->isSelectOptionEnabled( 'fake_webcrawler' );
22
+ }
23
+
24
+ /**
25
+ * @return bool
26
+ */
27
+ public function isEnabledInvalidUsernames() {
28
+ return $this->isSelectOptionEnabled( 'invalid_username' );
29
+ }
30
+
31
+ /**
32
+ * @return bool
33
+ */
34
+ public function isEnabledLinkCheese() {
35
+ return $this->isSelectOptionEnabled( 'link_cheese' );
36
+ }
37
+
38
+ /**
39
+ * @return bool
40
+ */
41
+ public function isEnabledXmlRpcDetect() {
42
+ return $this->isSelectOptionEnabled( 'xmlrpc' );
43
+ }
44
+
45
+ /**
46
+ * @return bool
47
+ */
48
+ public function isTransgression404() {
49
+ return $this->isSelectOptionTransgression( '404_detect' );
50
+ }
51
+
52
+ /**
53
+ * @return bool
54
+ */
55
+ public function isTransgressionLinkCheese() {
56
+ return $this->isSelectOptionTransgression( 'link_cheese' );
57
+ }
58
+
59
+ /**
60
+ * @return bool
61
+ */
62
+ public function isTransgressionInvalidUsernames() {
63
+ return $this->isSelectOptionTransgression( 'invalid_username' );
64
+ }
65
+
66
+ /**
67
+ * @return bool
68
+ */
69
+ public function isTransgressionFakeWebCrawler() {
70
+ return $this->isSelectOptionTransgression( 'fake_webcrawler' );
71
+ }
72
+
73
+ /**
74
+ * @return bool
75
+ */
76
+ public function isTransgressionXmlRpc() {
77
+ return $this->isSelectOptionTransgression( 'xmlrpc' );
78
+ }
79
+
80
+ /**
81
+ * @param string $sOptionKey
82
+ * @return bool
83
+ */
84
+ protected function isSelectOptionTransgression( $sOptionKey ) {
85
+ return $this->isOpt( $sOptionKey, 'transgression' );
86
+ }
87
+
88
+ /**
89
+ * @param string $sOptionKey
90
+ * @return bool
91
+ */
92
+ protected function isSelectOptionEnabled( $sOptionKey ) {
93
+ return !$this->isOpt( $sOptionKey, 'disabled' );
94
+ }
95
+
96
+ /**
97
+ * @return bool
98
+ */
99
+ private function getMouseTrapResponseType() {
100
+ return $this->getOpt( 'mousetrap_bot_response' );
101
+ }
102
+
103
+ /**
104
+ * @return bool
105
+ */
106
+ public function isMouseTrapEnabled() {
107
+ return $this->isPremium() && ( $this->getMouseTrapResponseType() != 'disabled' );
108
+ }
109
+
110
+ /**
111
+ * @return bool
112
+ */
113
+ public function isMouseTrayBlock() {
114
+ return $this->getMouseTrapResponseType() === 'block';
115
+ }
116
+
117
+ /**
118
+ * @return bool
119
+ */
120
+ public function isMouseTrapTransgression() {
121
+ return $this->getMouseTrapResponseType() === 'transgression';
122
+ }
123
+
124
+ /**
125
+ * @param array $aOptionsParams
126
+ * @return array
127
+ * @throws \Exception
128
+ */
129
+ protected function loadStrings_SectionTitles( $aOptionsParams ) {
130
+
131
+ switch ( $aOptionsParams[ 'slug' ] ) {
132
+
133
+ case 'section_enable_plugin_feature_mousetrap' :
134
+ $sTitle = _wpsf__( 'Identify And Capture Bots Based On Their Site Activity' );
135
+ $aSummary = array(
136
+ _wpsf__( "A bot doesn't know what's real and what's not, so it probes many different avenues until it finds something it recognises." ),
137
+ _wpsf__( "MouseTrap monitors a set of typical bot behaviours to help identify probing bots." ),
138
+ sprintf( '%s - %s', _wpsf__( 'Recommendation' ), _wpsf__( 'Enable as many mouse traps as possible.' ) )
139
+ );
140
+ $sTitleShort = _wpsf__( 'Bot MouseTrap' );
141
+ break;
142
+
143
+ case 'section_cheese' :
144
+ $sTitle = _wpsf__( 'Capture Bot Activity' );
145
+ $aSummary = [
146
+ sprintf( '%s - %s', _wpsf__( 'Recommendation' ), _wpsf__( "Enable as many options as possible." ) )
147
+ ];
148
+ $sTitleShort = _wpsf__( 'Bot Cheeses' );
149
+ break;
150
+
151
+ default:
152
+ list( $sTitle, $sTitleShort, $aSummary ) = $this->loadStrings_SectionTitlesDefaults( $aOptionsParams );
153
+ }
154
+ $aOptionsParams[ 'title' ] = $sTitle;
155
+ $aOptionsParams[ 'summary' ] = ( isset( $aSummary ) && is_array( $aSummary ) ) ? $aSummary : array();
156
+ $aOptionsParams[ 'title_short' ] = $sTitleShort;
157
+ return $aOptionsParams;
158
+ }
159
+
160
+ /**
161
+ * @param array $aOptionsParams
162
+ * @return array
163
+ * @throws \Exception
164
+ */
165
+ protected function loadStrings_Options( $aOptionsParams ) {
166
+
167
+ switch ( $aOptionsParams[ 'key' ] ) {
168
+
169
+ case 'enable_mousetrap' :
170
+ $sName = sprintf( _wpsf__( 'Enable %s Module' ), $this->getMainFeatureName() );
171
+ $sSummary = sprintf( _wpsf__( 'Enable (or Disable) The %s Module' ), $this->getMainFeatureName() );
172
+ $sDescription = sprintf( _wpsf__( 'Un-Checking this option will completely disable the %s module.' ), $this->getMainFeatureName() );
173
+ break;
174
+
175
+ case '404_detect' :
176
+ $sName = _wpsf__( '404 Detect' );
177
+ $sSummary = _wpsf__( 'Identify A Bot When It Hits A 404' );
178
+ $sDescription = _wpsf__( "Detect when a visitor tries to load a non-existent page." )
179
+ .'<br/>'._wpsf__( "Care should be taken to ensure you don't have legitimate links on your site that are 404s." );
180
+ break;
181
+
182
+ case 'link_cheese' :
183
+ $sName = _wpsf__( 'Link Cheese' );
184
+ $sSummary = _wpsf__( 'Tempt A Bot With A Link To Follow' );
185
+ $sDescription = _wpsf__( "Detect a bot when it follows a 'no-follow' link." );
186
+ break;
187
+
188
+ case 'invalid_username' :
189
+ $sName = _wpsf__( 'Invalid Usernames' );
190
+ $sSummary = _wpsf__( 'Detect Invalid Username Logins' );
191
+ $sDescription = _wpsf__( "Identify a Bot when it tries to login with a non-existent username" );
192
+ break;
193
+
194
+ case 'fake_webcrawler' :
195
+ $sName = _wpsf__( 'Fake Web Crawler' );
196
+ $sSummary = _wpsf__( 'Detect Fake Search Engine Crawlers' );
197
+ $sDescription = _wpsf__( "Identify a Bot when it presents as an official web crawler, but analysis shows it's fake." );
198
+ break;
199
+
200
+ default:
201
+ throw new \Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $aOptionsParams[ 'key' ] ) );
202
+ }
203
+
204
+ $aOptionsParams[ 'name' ] = $sName;
205
+ $aOptionsParams[ 'summary' ] = $sSummary;
206
+ $aOptionsParams[ 'description' ] = $sDescription;
207
+ return $aOptionsParams;
208
+ }
209
+ }
src/features/plugin.php CHANGED
@@ -44,7 +44,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
44
  * @return bool
45
  */
46
  public function getLastCheckServerIpAtHasExpired() {
47
- return ( ( $this->loadRequest()->ts() - $this->getLastCheckServerIpAt() ) > DAY_IN_SECONDS );
48
  }
49
 
50
  /**
@@ -76,7 +76,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
76
  */
77
  public function isDisplayPluginBadge() {
78
  return $this->isOpt( 'display_plugin_badge', 'Y' )
79
- && ( $this->loadRequest()->cookie( $this->getCookieIdBadgeState() ) != 'closed' );
80
  }
81
 
82
  /**
@@ -93,7 +93,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
93
  protected function setVisitorIp() {
94
  $oDetector = ( new Shield\Utilities\VisitorIpDetection() )
95
  ->setPotentialHostIps(
96
- [ $this->getMyServerIp(), $this->loadRequest()->server( 'SERVER_ADDR' ) ]
97
  );
98
  if ( !$this->isVisitorAddressSourceAutoDetect() ) {
99
  $oDetector->setPreferredSource( $this->getVisitorAddressSource() );
@@ -142,7 +142,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
142
  public function handleAjax( $aAjaxResponse ) {
143
 
144
  if ( empty( $aAjaxResponse ) ) {
145
- switch ( $this->loadRequest()->request( 'exec' ) ) {
146
 
147
  case 'plugin_badge_close':
148
  $aAjaxResponse = $this->ajaxExec_PluginBadgeClose();
@@ -169,7 +169,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
169
  public function handleAuthAjax( $aAjaxResponse ) {
170
 
171
  if ( empty( $aAjaxResponse ) ) {
172
- switch ( $this->loadRequest()->request( 'exec' ) ) {
173
 
174
  case 'bulk_action':
175
  $aAjaxResponse = $this->ajaxExec_BulkItemAction();
@@ -205,8 +205,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
205
  /**
206
  */
207
  public function handleModRequest() {
208
- $oReq = $this->loadRequest();
209
- switch ( $oReq->request( 'exec' ) ) {
210
 
211
  case 'export_file_download':
212
  header( 'Set-Cookie: fileDownload=true; path=/' );
@@ -231,7 +230,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
231
  }
232
  $this->loadWpNotices()
233
  ->addFlashUserMessage( $sMessage, !$bSuccess );
234
- $this->loadWp()->doRedirect( $this->getUrlImportExport() );
235
  break;
236
 
237
  default:
@@ -245,7 +244,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
245
  */
246
  private function getUrlImportExport() {
247
  return add_query_arg(
248
- [ 'subnav' => 'importexport' ],
249
  $this->getCon()->getModule( 'insights' )->getUrl_AdminPage()
250
  );
251
  }
@@ -254,7 +253,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
254
  * @return array
255
  */
256
  private function ajaxExec_BulkItemAction() {
257
- $oReq = $this->loadRequest();
258
 
259
  $bSuccess = false;
260
 
@@ -308,7 +307,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
308
  * @return array
309
  */
310
  public function ajaxExec_SetPluginTrackingPerm() {
311
- $this->setPluginTrackingPermission( (bool)$this->loadRequest()->query( 'agree', false ) );
312
  return array( 'success' => true );
313
  }
314
 
@@ -349,7 +348,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
349
  */
350
  protected function ajaxExec_AdminNotesDelete() {
351
 
352
- $sItemId = $this->loadRequest()->post( 'rid' );
353
  if ( empty( $sItemId ) ) {
354
  $sMessage = _wpsf__( 'Note not found.' );
355
  }
@@ -466,7 +465,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
466
  */
467
  public function setPluginTrackingPermission( $bOnOrOff = true ) {
468
  $this->setOpt( 'enable_tracking', $bOnOrOff ? 'Y' : 'N' )
469
- ->setOpt( 'tracking_permission_set_at', $this->loadRequest()->ts() )
470
  ->savePluginOptions();
471
  return $this;
472
  }
@@ -523,7 +522,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
523
  public function getLinkToTrackingDataDump() {
524
  return add_query_arg(
525
  array( 'shield_action' => 'dump_tracking_data' ),
526
- $this->loadWp()->getUrl_WpAdmin()
527
  );
528
  }
529
 
@@ -545,14 +544,14 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
545
  * @return $this
546
  */
547
  public function setTrackingLastSentAt() {
548
- return $this->setOpt( 'tracking_last_sent_at', $this->loadRequest()->ts() );
549
  }
550
 
551
  /**
552
  * @return bool
553
  */
554
  public function readyToSendTrackingData() {
555
- return ( ( $this->loadRequest()->ts() - $this->getTrackingLastSentAt() ) > WEEK_IN_SECONDS );
556
  }
557
 
558
  /**
@@ -561,7 +560,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
561
  */
562
  public function supplyPluginReportEmail( $sEmail = '' ) {
563
  $sE = $this->getOpt( 'block_send_email_address' );
564
- return $this->loadDP()->validEmail( $sE ) ? $sE : $sEmail;
565
  }
566
 
567
  /**
@@ -572,7 +571,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
572
  $this->storeRealInstallDate();
573
 
574
  if ( $this->isTrackingEnabled() && !$this->isTrackingPermissionSet() ) {
575
- $this->setOpt( 'tracking_permission_set_at', $this->loadRequest()->ts() );
576
  }
577
 
578
  $this->cleanRecaptchaKey( 'google_recaptcha_site_key' );
@@ -588,7 +587,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
588
  * @return int
589
  */
590
  public function getFirstInstallDate() {
591
- return $this->loadWp()->getOption( $this->prefixOptionKey( 'install_date' ) );
592
  }
593
 
594
  /**
@@ -602,8 +601,8 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
602
  * @return int - the real install timestamp
603
  */
604
  public function storeRealInstallDate() {
605
- $oWP = $this->loadWp();
606
- $nNow = $this->loadRequest()->ts();
607
 
608
  $sOptKey = $this->prefixOptionKey( 'install_date' );
609
 
@@ -674,8 +673,8 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
674
  protected function genInstallId() {
675
  return sha1(
676
  $this->getInstallDate()
677
- .$this->loadWp()->getWpUrl()
678
- .$this->loadDbProcessor()->getPrefix()
679
  );
680
  }
681
 
@@ -691,7 +690,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
691
  */
692
  public function hasImportExportMasterImportUrl() {
693
  $sMaster = $this->getImportExportMasterImportUrl();
694
- return !empty( $sMaster );// && ( rtrim( $this->loadWp()->getHomeUrl(), '/' ) != $sMaster );
695
  }
696
 
697
  /**
@@ -705,7 +704,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
705
  * @return int
706
  */
707
  public function getImportExportHandshakeExpiresAt() {
708
- return $this->getOpt( 'importexport_handshake_expires_at', $this->loadRequest()->ts() );
709
  }
710
 
711
  /**
@@ -731,7 +730,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
731
  if ( empty( $sId ) || $this->isImportExportSecretKeyExpired() ) {
732
  $sId = sha1( $this->getPluginInstallationId().wp_rand( 0, PHP_INT_MAX ) );
733
  $this->setOpt( 'importexport_secretkey', $sId )
734
- ->setOpt( 'importexport_secretkey_expires_at', $this->loadRequest()->ts() + HOUR_IN_SECONDS );
735
  }
736
  return $sId;
737
  }
@@ -747,7 +746,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
747
  * @return bool
748
  */
749
  protected function isImportExportSecretKeyExpired() {
750
- return ( $this->loadRequest()->ts() > $this->getOpt( 'importexport_secretkey_expires_at' ) );
751
  }
752
 
753
  /**
@@ -831,7 +830,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
831
  * @return $this
832
  */
833
  public function startImportExportHandshake() {
834
- $this->setOpt( 'importexport_handshake_expires_at', $this->loadRequest()->ts() + 30 )
835
  ->savePluginOptions();
836
  return $this;
837
  }
@@ -866,7 +865,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
866
  * @return array
867
  */
868
  private function buildIpAddressMap() {
869
- $oReq = $this->loadRequest();
870
 
871
  $aOptionData = $this->getOptionsVo()->getRawData_SingleOption( 'visitor_address_source' );
872
  $aValueOptions = $aOptionData[ 'value_options' ];
@@ -932,7 +931,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
932
  * @return array
933
  */
934
  protected function getDisplayStrings() {
935
- return $this->loadDP()->mergeArraysRecursive(
936
  parent::getDisplayStrings(),
937
  array(
938
  'actions_title' => _wpsf__( 'Plugin Actions' ),
@@ -966,13 +965,13 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
966
  * @return bool
967
  */
968
  public function getCanAdminNotes() {
969
- return $this->isPremium() && $this->loadWpUsers()->isUserAdmin();
970
  }
971
 
972
  public function insertCustomJsVars_Admin() {
973
  parent::insertCustomJsVars_Admin();
974
 
975
- if ( $this->loadWp()->isCurrentPage( 'plugins.php' ) ) {
976
  $sFile = $this->getCon()->getPluginBaseFile();
977
  wp_localize_script(
978
  $this->prefix( 'global-plugin' ),
@@ -983,7 +982,7 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
983
  'send_deactivate_survey' => $this->getAjaxActionData( 'send_deactivate_survey' ),
984
  ),
985
  'hrefs' => array(
986
- 'deactivate' => $this->loadWpPlugins()->getUrl_Deactivate( $sFile ),
987
  ),
988
  )
989
  );
@@ -1019,13 +1018,13 @@ class ICWP_WPSF_FeatureHandler_Plugin extends ICWP_WPSF_FeatureHandler_BaseWpsf
1019
  'href' => $this->getUrl_DirectLinkToOption( 'visitor_address_source' ),
1020
  );
1021
 
1022
- $bHasSupportEmail = $this->loadDP()->validEmail( $this->supplyPluginReportEmail() );
1023
  $aThis[ 'key_opts' ][ 'reports' ] = array(
1024
  'name' => _wpsf__( 'Reporting Email' ),
1025
  'enabled' => $bHasSupportEmail,
1026
  'summary' => $bHasSupportEmail ?
1027
  sprintf( _wpsf__( 'Email address for reports set to: %s' ), $this->supplyPluginReportEmail() )
1028
- : sprintf( _wpsf__( 'No address provided - defaulting to: %s' ), $this->loadWp()
1029
  ->getSiteAdminEmail() ),
1030
  'weight' => 0,
1031
  'href' => $this->getUrl_DirectLinkToOption( 'block_send_email_address' ),
44
  * @return bool
45
  */
46
  public function getLastCheckServerIpAtHasExpired() {
47
+ return ( Services::Request()->ts() - $this->getLastCheckServerIpAt() > DAY_IN_SECONDS );
48
  }
49
 
50
  /**
76
  */
77
  public function isDisplayPluginBadge() {
78
  return $this->isOpt( 'display_plugin_badge', 'Y' )
79
+ && ( Services::Request()->cookie( $this->getCookieIdBadgeState() ) != 'closed' );
80
  }
81
 
82
  /**
93
  protected function setVisitorIp() {
94
  $oDetector = ( new Shield\Utilities\VisitorIpDetection() )
95
  ->setPotentialHostIps(
96
+ [ $this->getMyServerIp(), Services::Request()->getServerAddress() ]
97
  );
98
  if ( !$this->isVisitorAddressSourceAutoDetect() ) {
99
  $oDetector->setPreferredSource( $this->getVisitorAddressSource() );
142
  public function handleAjax( $aAjaxResponse ) {
143
 
144
  if ( empty( $aAjaxResponse ) ) {
145
+ switch ( Services::Request()->request( 'exec' ) ) {
146
 
147
  case 'plugin_badge_close':
148
  $aAjaxResponse = $this->ajaxExec_PluginBadgeClose();
169
  public function handleAuthAjax( $aAjaxResponse ) {
170
 
171
  if ( empty( $aAjaxResponse ) ) {
172
+ switch ( Services::Request()->request( 'exec' ) ) {
173
 
174
  case 'bulk_action':
175
  $aAjaxResponse = $this->ajaxExec_BulkItemAction();
205
  /**
206
  */
207
  public function handleModRequest() {
208
+ switch ( Services::Request()->request( 'exec' ) ) {
 
209
 
210
  case 'export_file_download':
211
  header( 'Set-Cookie: fileDownload=true; path=/' );
230
  }
231
  $this->loadWpNotices()
232
  ->addFlashUserMessage( $sMessage, !$bSuccess );
233
+ Services::Response()->redirect( $this->getUrlImportExport() );
234
  break;
235
 
236
  default:
244
  */
245
  private function getUrlImportExport() {
246
  return add_query_arg(
247
+ [ 'inav' => 'importexport' ],
248
  $this->getCon()->getModule( 'insights' )->getUrl_AdminPage()
249
  );
250
  }
253
  * @return array
254
  */
255
  private function ajaxExec_BulkItemAction() {
256
+ $oReq = Services::Request();
257
 
258
  $bSuccess = false;
259
 
307
  * @return array
308
  */
309
  public function ajaxExec_SetPluginTrackingPerm() {
310
+ $this->setPluginTrackingPermission( (bool)Services::Request()->query( 'agree', false ) );
311
  return array( 'success' => true );
312
  }
313
 
348
  */
349
  protected function ajaxExec_AdminNotesDelete() {
350
 
351
+ $sItemId = Services::Request()->post( 'rid' );
352
  if ( empty( $sItemId ) ) {
353
  $sMessage = _wpsf__( 'Note not found.' );
354
  }
465
  */
466
  public function setPluginTrackingPermission( $bOnOrOff = true ) {
467
  $this->setOpt( 'enable_tracking', $bOnOrOff ? 'Y' : 'N' )
468
+ ->setOpt( 'tracking_permission_set_at', Services::Request()->ts() )
469
  ->savePluginOptions();
470
  return $this;
471
  }
522
  public function getLinkToTrackingDataDump() {
523
  return add_query_arg(
524
  array( 'shield_action' => 'dump_tracking_data' ),
525
+ Services::WpGeneral()->getAdminUrl()
526
  );
527
  }
528
 
544
  * @return $this
545
  */
546
  public function setTrackingLastSentAt() {
547
+ return $this->setOpt( 'tracking_last_sent_at', Services::Request()->ts() );
548
  }
549
 
550
  /**
551
  * @return bool
552
  */
553
  public function readyToSendTrackingData() {
554
+ return ( Services::Request()->ts() - $this->getTrackingLastSentAt() > WEEK_IN_SECONDS );
555
  }
556
 
557
  /**
560
  */
561
  public function supplyPluginReportEmail( $sEmail = '' ) {
562
  $sE = $this->getOpt( 'block_send_email_address' );
563
+ return Services::Data()->validEmail( $sE ) ? $sE : $sEmail;
564
  }
565
 
566
  /**
571
  $this->storeRealInstallDate();
572
 
573
  if ( $this->isTrackingEnabled() && !$this->isTrackingPermissionSet() ) {
574
+ $this->setOpt( 'tracking_permission_set_at', Services::Request()->ts() );
575
  }
576
 
577
  $this->cleanRecaptchaKey( 'google_recaptcha_site_key' );
587
  * @return int
588
  */
589
  public function getFirstInstallDate() {
590
+ return Services::WpGeneral()->getOption( $this->prefixOptionKey( 'install_date' ) );
591
  }
592
 
593
  /**
601
  * @return int - the real install timestamp
602
  */
603
  public function storeRealInstallDate() {
604
+ $oWP = Services::WpGeneral();
605
+ $nNow = Services::Request()->ts();
606
 
607
  $sOptKey = $this->prefixOptionKey( 'install_date' );
608
 
673
  protected function genInstallId() {
674
  return sha1(
675
  $this->getInstallDate()
676
+ .Services::WpGeneral()->getWpUrl()
677
+ .Services::WpDb()->getPrefix()
678
  );
679
  }
680
 
690
  */
691
  public function hasImportExportMasterImportUrl() {
692
  $sMaster = $this->getImportExportMasterImportUrl();
693
+ return !empty( $sMaster );
694
  }
695
 
696
  /**
704
  * @return int
705
  */
706
  public function getImportExportHandshakeExpiresAt() {
707
+ return $this->getOpt( 'importexport_handshake_expires_at', Services::Request()->ts() );
708
  }
709
 
710
  /**
730
  if ( empty( $sId ) || $this->isImportExportSecretKeyExpired() ) {
731
  $sId = sha1( $this->getPluginInstallationId().wp_rand( 0, PHP_INT_MAX ) );
732
  $this->setOpt( 'importexport_secretkey', $sId )
733
+ ->setOpt( 'importexport_secretkey_expires_at', Services::Request()->ts() + HOUR_IN_SECONDS );
734
  }
735
  return $sId;
736
  }
746
  * @return bool
747
  */
748
  protected function isImportExportSecretKeyExpired() {
749
+ return ( Services::Request()->ts() > $this->getOpt( 'importexport_secretkey_expires_at' ) );
750
  }
751
 
752
  /**
830
  * @return $this
831
  */
832
  public function startImportExportHandshake() {
833
+ $this->setOpt( 'importexport_handshake_expires_at', Services::Request()->ts() + 30 )
834
  ->savePluginOptions();
835
  return $this;
836
  }
865
  * @return array
866
  */
867
  private function buildIpAddressMap() {
868
+ $oReq = Services::Request();
869
 
870
  $aOptionData = $this->getOptionsVo()->getRawData_SingleOption( 'visitor_address_source' );
871
  $aValueOptions = $aOptionData[ 'value_options' ];
931
  * @return array
932
  */
933
  protected function getDisplayStrings() {
934
+ return Services::DataManipulation()->mergeArraysRecursive(
935
  parent::getDisplayStrings(),
936
  array(
937
  'actions_title' => _wpsf__( 'Plugin Actions' ),
965
  * @return bool
966
  */
967
  public function getCanAdminNotes() {
968
+ return $this->isPremium() && Services::WpUsers()->isUserAdmin();
969
  }
970
 
971
  public function insertCustomJsVars_Admin() {
972
  parent::insertCustomJsVars_Admin();
973
 
974
+ if ( Services::WpPost()->isCurrentPage( 'plugins.php' ) ) {
975
  $sFile = $this->getCon()->getPluginBaseFile();
976
  wp_localize_script(
977
  $this->prefix( 'global-plugin' ),
982
  'send_deactivate_survey' => $this->getAjaxActionData( 'send_deactivate_survey' ),
983
  ),
984
  'hrefs' => array(
985
+ 'deactivate' => Services::WpPlugins()->getUrl_Deactivate( $sFile ),
986
  ),
987
  )
988
  );
1018
  'href' => $this->getUrl_DirectLinkToOption( 'visitor_address_source' ),
1019
  );
1020
 
1021
+ $bHasSupportEmail = Services::Data()->validEmail( $this->supplyPluginReportEmail() );
1022
  $aThis[ 'key_opts' ][ 'reports' ] = array(
1023
  'name' => _wpsf__( 'Reporting Email' ),
1024
  'enabled' => $bHasSupportEmail,
1025
  'summary' => $bHasSupportEmail ?
1026
  sprintf( _wpsf__( 'Email address for reports set to: %s' ), $this->supplyPluginReportEmail() )
1027
+ : sprintf( _wpsf__( 'No address provided - defaulting to: %s' ), Services::WpGeneral()
1028
  ->getSiteAdminEmail() ),
1029
  'weight' => 0,
1030
  'href' => $this->getUrl_DirectLinkToOption( 'block_send_email_address' ),
src/features/sessions.php CHANGED
@@ -18,12 +18,13 @@ class ICWP_WPSF_FeatureHandler_Sessions extends ICWP_WPSF_FeatureHandler_BaseWps
18
  * @return bool
19
  */
20
  public function isAutoAddSessions() {
 
21
  $nStartedAt = $this->getOpt( 'autoadd_sessions_started_at', 0 );
22
  if ( $nStartedAt < 1 ) {
23
- $nStartedAt = $this->loadRequest()->ts();
24
  $this->setOpt( 'autoadd_sessions_started_at', $nStartedAt );
25
  }
26
- return ( $this->loadRequest()->ts() - $nStartedAt ) < 20;
27
  }
28
 
29
  /**
18
  * @return bool
19
  */
20
  public function isAutoAddSessions() {
21
+ $oReq = Services::Request();
22
  $nStartedAt = $this->getOpt( 'autoadd_sessions_started_at', 0 );
23
  if ( $nStartedAt < 1 ) {
24
+ $nStartedAt = $oReq->ts();
25
  $this->setOpt( 'autoadd_sessions_started_at', $nStartedAt );
26
  }
27
+ return ( $oReq->ts() - $nStartedAt ) < 20;
28
  }
29
 
30
  /**
src/features/traffic.php CHANGED
@@ -9,7 +9,7 @@ class ICWP_WPSF_FeatureHandler_Traffic extends ICWP_WPSF_FeatureHandler_BaseWpsf
9
  * Hooked to the plugin's main plugin_shutdown action
10
  */
11
  public function action_doFeatureShutdown() {
12
- if ( $this->isAutoDisable() && $this->loadRequest()->ts() - $this->getAutoDisableAt() > 0 ) {
13
  $this->setOpt( 'auto_disable', 'N' )
14
  ->setOpt( 'autodisable_at', 0 )
15
  ->setIsMainFeatureEnabled( false );
@@ -26,7 +26,7 @@ class ICWP_WPSF_FeatureHandler_Traffic extends ICWP_WPSF_FeatureHandler_BaseWpsf
26
  $oPro->getProcessorLogger()
27
  ->cleanupDatabase();
28
 
29
- $this->setOpt( 'autodisable_at', $this->isAutoDisable() ? $this->loadRequest()->ts() + WEEK_IN_SECONDS : 0 );
30
 
31
  $aExcls = $this->getCustomExclusions();
32
  foreach ( $aExcls as &$sExcl ) {
@@ -104,7 +104,7 @@ class ICWP_WPSF_FeatureHandler_Traffic extends ICWP_WPSF_FeatureHandler_BaseWpsf
104
  * @return string
105
  */
106
  protected function getAutoDisableTimestamp() {
107
- return $this->loadWp()->getTimeStampForDisplay( $this->getAutoDisableAt() );
108
  }
109
 
110
  /**
@@ -170,7 +170,7 @@ class ICWP_WPSF_FeatureHandler_Traffic extends ICWP_WPSF_FeatureHandler_BaseWpsf
170
  public function handleAuthAjax( $aAjaxResponse ) {
171
 
172
  if ( empty( $aAjaxResponse ) ) {
173
- switch ( $this->loadRequest()->request( 'exec' ) ) {
174
 
175
  case 'render_table_traffic':
176
  $aAjaxResponse = $this->ajaxExec_BuildTableTraffic();
9
  * Hooked to the plugin's main plugin_shutdown action
10
  */
11
  public function action_doFeatureShutdown() {
12
+ if ( $this->isAutoDisable() && Services::Request()->ts() - $this->getAutoDisableAt() > 0 ) {
13
  $this->setOpt( 'auto_disable', 'N' )
14
  ->setOpt( 'autodisable_at', 0 )
15
  ->setIsMainFeatureEnabled( false );
26
  $oPro->getProcessorLogger()
27
  ->cleanupDatabase();
28
 
29
+ $this->setOpt( 'autodisable_at', $this->isAutoDisable() ? Services::Request()->ts() + WEEK_IN_SECONDS : 0 );
30
 
31
  $aExcls = $this->getCustomExclusions();
32
  foreach ( $aExcls as &$sExcl ) {
104
  * @return string
105
  */
106
  protected function getAutoDisableTimestamp() {
107
+ return Services::WpGeneral()->getTimeStampForDisplay( $this->getAutoDisableAt() );
108
  }
109
 
110
  /**
170
  public function handleAuthAjax( $aAjaxResponse ) {
171
 
172
  if ( empty( $aAjaxResponse ) ) {
173
+ switch ( Services::Request()->request( 'exec' ) ) {
174
 
175
  case 'render_table_traffic':
176
  $aAjaxResponse = $this->ajaxExec_BuildTableTraffic();
src/features/user_management.php CHANGED
@@ -12,7 +12,7 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
12
  public function handleAuthAjax( $aAjaxResponse ) {
13
 
14
  if ( empty( $aAjaxResponse ) ) {
15
- switch ( $this->loadRequest()->request( 'exec' ) ) {
16
 
17
  case 'render_table_sessions':
18
  $aAjaxResponse = $this->ajaxExec_BuildTableTraffic();
@@ -37,7 +37,7 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
37
  * @return array
38
  */
39
  private function ajaxExec_BulkItemAction() {
40
- $oReq = $this->loadRequest();
41
  $oProcessor = $this->getSessionsProcessor();
42
 
43
  $bSuccess = false;
@@ -84,7 +84,7 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
84
  * @return array
85
  */
86
  private function ajaxExec_SessionDelete() {
87
- $oReq = $this->loadRequest();
88
  $oProcessor = $this->getSessionsProcessor();
89
 
90
  $bSuccess = false;
@@ -168,7 +168,7 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
168
 
169
  protected function doExtraSubmitProcessing() {
170
  $sAdminEmail = $this->getOpt( 'enable_admin_login_email_notification' );
171
- if ( !$this->loadDP()->validEmail( $sAdminEmail ) ) {
172
  $this->getOptionsVo()->resetOptToDefault( 'enable_admin_login_email_notification' );
173
  }
174
 
@@ -223,10 +223,10 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
223
  public function isAutoAddSessions() {
224
  $nStartedAt = $this->getOpt( 'autoadd_sessions_started_at', 0 );
225
  if ( $nStartedAt < 1 ) {
226
- $nStartedAt = $this->loadRequest()->ts();
227
  $this->setOpt( 'autoadd_sessions_started_at', $nStartedAt );
228
  }
229
- return ( $this->loadRequest()->ts() - $nStartedAt ) < 20;
230
  }
231
 
232
  /**
@@ -240,7 +240,7 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
240
  * @return bool
241
  */
242
  public function isSendAdminEmailLoginNotification() {
243
- return $this->loadDP()->validEmail( $this->getAdminLoginNotificationEmail() );
244
  }
245
 
246
  /**
@@ -254,14 +254,14 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
254
  * @return int days
255
  */
256
  public function getPassExpireDays() {
257
- return max( 0, (int)$this->getOpt( 'pass_expire' ) );
258
  }
259
 
260
  /**
261
  * @return int seconds
262
  */
263
  public function getPassExpireTimeout() {
264
- return $this->isPremium() ? $this->getPassExpireDays()*DAY_IN_SECONDS : 0;
265
  }
266
 
267
  /**
@@ -308,6 +308,13 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
308
  return $this->isOpt( 'pass_force_existing', 'Y' );
309
  }
310
 
 
 
 
 
 
 
 
311
  /**
312
  * @return bool
313
  */
@@ -315,12 +322,71 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
315
  return $this->isOpt( 'pass_prevent_pwned', 'Y' );
316
  }
317
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
  /**
319
  * @param array $aAllNotices
320
  * @return array
321
  */
322
  public function addInsightsNoticeData( $aAllNotices ) {
323
- $oWpUsers = $this->loadWpUsers();
324
 
325
  $aNotices = array(
326
  'title' => _wpsf__( 'Users' ),
@@ -328,7 +394,7 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
328
  );
329
 
330
  { //admin user
331
- $oAdmin = $oWpUsers->getUserByUsername( 'admin' );
332
  if ( !empty( $oAdmin ) && user_can( $oAdmin, 'manage_options' ) ) {
333
  $aNotices[ 'messages' ][ 'admin' ] = array(
334
  'title' => 'Admin User',
@@ -482,6 +548,15 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
482
  $sTitleShort = _wpsf__( 'Session Options' );
483
  break;
484
 
 
 
 
 
 
 
 
 
 
485
  default:
486
  throw new \Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
487
  }
@@ -527,7 +602,7 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
527
  .'<br />'._wpsf__( 'Think of this as an absolute maximum possible session length.' )
528
  .'<br />'.sprintf( _wpsf__( 'This cannot be less than %s.' ), '<strong>1</strong>' )
529
  .' '.sprintf( '%s: %s', _wpsf__( 'Default' ), '<strong>'.$this->getOptionsVo()
530
- ->getOptDefault( 'session_timeout_interval' ).'</strong>' );
531
  break;
532
 
533
  case 'session_idle_timeout_interval' :
@@ -590,6 +665,31 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
590
  .'<br/>'._wpsf__( 'Set to Zero(0) to disable.' );
591
  break;
592
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
593
  default:
594
  throw new \Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
595
  }
@@ -599,28 +699,4 @@ class ICWP_WPSF_FeatureHandler_UserManagement extends ICWP_WPSF_FeatureHandler_B
599
  $aOptionsParams[ 'description' ] = $sDescription;
600
  return $aOptionsParams;
601
  }
602
-
603
- /**
604
- * @deprecated
605
- * @return int
606
- */
607
- public function getSessionIdleTimeoutInterval() {
608
- return $this->getIdleTimeoutInterval();
609
- }
610
-
611
- /**
612
- * @deprecated 7.0.4
613
- * @return int
614
- */
615
- public function getSessionTimeoutInterval() {
616
- return $this->getMaxSessionTime();
617
- }
618
-
619
- /**
620
- * @deprecated 7.0.4
621
- * @return bool
622
- */
623
- public function hasSessionTimeoutInterval() {
624
- return $this->hasMaxSessionTimeout();
625
- }
626
  }
12
  public function handleAuthAjax( $aAjaxResponse ) {
13
 
14
  if ( empty( $aAjaxResponse ) ) {
15
+ switch ( Services::Request()->request( 'exec' ) ) {
16
 
17
  case 'render_table_sessions':
18
  $aAjaxResponse = $this->ajaxExec_BuildTableTraffic();
37
  * @return array
38
  */
39
  private function ajaxExec_BulkItemAction() {
40
+ $oReq = Services::Request();
41
  $oProcessor = $this->getSessionsProcessor();
42
 
43
  $bSuccess = false;
84
  * @return array
85
  */
86
  private function ajaxExec_SessionDelete() {
87
+ $oReq = Services::Request();
88
  $oProcessor = $this->getSessionsProcessor();
89
 
90
  $bSuccess = false;
168
 
169
  protected function doExtraSubmitProcessing() {
170
  $sAdminEmail = $this->getOpt( 'enable_admin_login_email_notification' );
171
+ if ( !Services::Data()->validEmail( $sAdminEmail ) ) {
172
  $this->getOptionsVo()->resetOptToDefault( 'enable_admin_login_email_notification' );
173
  }
174
 
223
  public function isAutoAddSessions() {
224
  $nStartedAt = $this->getOpt( 'autoadd_sessions_started_at', 0 );
225
  if ( $nStartedAt < 1 ) {
226
+ $nStartedAt = Services::Request()->ts();
227
  $this->setOpt( 'autoadd_sessions_started_at', $nStartedAt );
228
  }
229
+ return ( Services::Request()->ts() - $nStartedAt ) < 20;
230
  }
231
 
232
  /**
240
  * @return bool
241
  */
242
  public function isSendAdminEmailLoginNotification() {
243
+ return Services::Data()->validEmail( $this->getAdminLoginNotificationEmail() );
244
  }
245
 
246
  /**
254
  * @return int days
255
  */
256
  public function getPassExpireDays() {
257
+ return ( $this->isPasswordPoliciesEnabled() && $this->isPremium() ) ? (int)$this->getOpt( 'pass_expire' ) : 0;
258
  }
259
 
260
  /**
261
  * @return int seconds
262
  */
263
  public function getPassExpireTimeout() {
264
+ return $this->getPassExpireDays()*DAY_IN_SECONDS;
265
  }
266
 
267
  /**
308
  return $this->isOpt( 'pass_force_existing', 'Y' );
309
  }
310
 
311
+ /**
312
+ * @return bool
313
+ */
314
+ public function isPassExpirationEnabled() {
315
+ return $this->isPasswordPoliciesEnabled() && ( $this->getPassExpireTimeout() > 0 );
316
+ }
317
+
318
  /**
319
  * @return bool
320
  */
322
  return $this->isOpt( 'pass_prevent_pwned', 'Y' );
323
  }
324
 
325
+ public function isSuspendEnabled() {
326
+ return ( $this->isSuspendManualEnabled()
327
+ || $this->isSuspendAutoIdleEnabled()
328
+ || $this->isSuspendAutoPasswordEnabled()
329
+ ) && $this->isPremium();
330
+ }
331
+
332
+ /**
333
+ * @return bool
334
+ */
335
+ public function isSuspendManualEnabled() {
336
+ return $this->isOpt( 'manual_suspend', 'Y' );
337
+ }
338
+
339
+ /**
340
+ * @return int
341
+ */
342
+ public function getSuspendAutoIdleTime() {
343
+ return $this->getOpt( 'auto_idle', 0 )*DAY_IN_SECONDS;
344
+ }
345
+
346
+ /**
347
+ * @return bool
348
+ */
349
+ public function isSuspendAutoIdleEnabled() {
350
+ return $this->getSuspendAutoIdleTime() > 0;
351
+ }
352
+
353
+ /**
354
+ * @return bool
355
+ */
356
+ public function isSuspendAutoPasswordEnabled() {
357
+ return $this->isOpt( 'auto_password', 'Y' )
358
+ && $this->isPasswordPoliciesEnabled() && $this->getPassExpireTimeout();
359
+ }
360
+
361
+ /**
362
+ * @param int $nId
363
+ * @param bool $bAdd - set true to add, false to remove
364
+ * @return $this
365
+ */
366
+ public function addRemoveHardSuspendUserId( $nId, $bAdd = true ) {
367
+ $aIds = $this->getOpt( 'hard_suspended_userids', [] );
368
+ if ( $bAdd ) {
369
+ $aIds[ $nId ] = Services::Request()->ts();
370
+ }
371
+ else if ( isset( $aIds[ $nId ] ) ) {
372
+ unset( $aIds[ $nId ] );
373
+ }
374
+ return $this->setOpt( 'hard_suspended_userids', $aIds );
375
+ }
376
+
377
+ /**
378
+ * @return array
379
+ */
380
+ public function getSuspendHardUserIds() {
381
+ $aIds = $this->getOpt( 'hard_suspended_userids', [] );
382
+ return is_array( $aIds ) ? array_filter( $aIds, 'is_int' ) : [];
383
+ }
384
+
385
  /**
386
  * @param array $aAllNotices
387
  * @return array
388
  */
389
  public function addInsightsNoticeData( $aAllNotices ) {
 
390
 
391
  $aNotices = array(
392
  'title' => _wpsf__( 'Users' ),
394
  );
395
 
396
  { //admin user
397
+ $oAdmin = Services::WpUsers()->getUserByUsername( 'admin' );
398
  if ( !empty( $oAdmin ) && user_can( $oAdmin, 'manage_options' ) ) {
399
  $aNotices[ 'messages' ][ 'admin' ] = array(
400
  'title' => 'Admin User',
548
  $sTitleShort = _wpsf__( 'Session Options' );
549
  break;
550
 
551
+ case 'section_suspend' :
552
+ $sTitleShort = _wpsf__( 'User Suspension' );
553
+ $sTitle = _wpsf__( 'Automatic And Manual User Suspension' );
554
+ $aSummary = array(
555
+ sprintf( '%s - %s', _wpsf__( 'Purpose' ), _wpsf__( 'Automatically suspend accounts to prevent login by certain users.' ) ),
556
+ sprintf( '%s - %s', _wpsf__( 'Recommendation' ), _wpsf__( 'Use of this feature is highly recommend.' ) )
557
+ );
558
+ break;
559
+
560
  default:
561
  throw new \Exception( sprintf( 'A section slug was defined but with no associated strings. Slug: "%s".', $sSectionSlug ) );
562
  }
602
  .'<br />'._wpsf__( 'Think of this as an absolute maximum possible session length.' )
603
  .'<br />'.sprintf( _wpsf__( 'This cannot be less than %s.' ), '<strong>1</strong>' )
604
  .' '.sprintf( '%s: %s', _wpsf__( 'Default' ), '<strong>'.$this->getOptionsVo()
605
+ ->getOptDefault( 'session_timeout_interval' ).'</strong>' );
606
  break;
607
 
608
  case 'session_idle_timeout_interval' :
665
  .'<br/>'._wpsf__( 'Set to Zero(0) to disable.' );
666
  break;
667
 
668
+ case 'manual_suspend' :
669
+ $sName = _wpsf__( 'Allow Manual User Suspension' );
670
+ $sSummary = _wpsf__( 'Manually Suspend User Accounts To Prevent Login' );
671
+ $sDescription = _wpsf__( 'Users may be forcefully suspended by administrators to prevent future login.' );
672
+ break;
673
+
674
+ case 'auto_password' :
675
+ $sName = _wpsf__( 'Auto-Suspend Expired Passwords' );
676
+ $sSummary = _wpsf__( 'Automatically Suspend Users With Expired Passwords' );
677
+ $sDescription = _wpsf__( 'Automatically suspend login by users and require password reset to unsuspend.' )
678
+ .'<br/>'.sprintf(
679
+ '<strong>%s</strong> - %s',
680
+ _wpsf__( 'Important' ),
681
+ _wpsf__( 'Requires password expiration policy to be set.' )
682
+ );
683
+ break;
684
+
685
+ case 'auto_idle' :
686
+ $sName = _wpsf__( 'Auto-Suspend Idle Users' );
687
+ $sSummary = _wpsf__( 'Automatically Suspend Idle User Accounts' );
688
+ $sDescription = _wpsf__( 'Automatically suspend login by idle users and require password reset to unsuspend.' )
689
+ .'<br/>'._wpsf__( 'Specify the number of days since last login to consider a user as idle.' )
690
+ .'<br/>'._wpsf__( 'Set to Zero(0) to disable.' );
691
+ break;
692
+
693
  default:
694
  throw new \Exception( sprintf( 'An option has been defined but without strings assigned to it. Option key: "%s".', $sKey ) );
695
  }
699
  $aOptionsParams[ 'description' ] = $sDescription;
700
  return $aOptionsParams;
701
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
702
  }
src/lib/src/ChangeTrack/Diff/Base.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Diff;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot\SnapshotsConsumer;
6
+
7
+ class Base {
8
+
9
+ use SnapshotsConsumer;
10
+
11
+ /**
12
+ * @return array[]
13
+ */
14
+ public function run() {
15
+ return [
16
+ 'added' => $this->getAdded(),
17
+ 'removed' => $this->getRemoved(),
18
+ 'changed' => $this->getChangedItems(),
19
+ ];
20
+ }
21
+
22
+ /**
23
+ * @return array
24
+ */
25
+ protected function getAdded() {
26
+ return array_diff_key( $this->getNewSnapshot(), $this->getOldSnapshot() );
27
+ }
28
+
29
+ /**
30
+ * @return array - key is the ID of the item, value is array of changed attributes
31
+ */
32
+ protected function getChangedItems() {
33
+ $aChanged = [];
34
+
35
+ $aCompareAttrs = $this->getAttributesToCompare();
36
+ foreach ( array_keys( $this->getCommonElements() ) as $nId ) {
37
+ $aOld = $this->getOldSnapshot()[ $nId ];
38
+ $aNew = $this->getNewSnapshot()[ $nId ];
39
+
40
+ $aChanged[ $nId ] = [];
41
+ foreach ( $aCompareAttrs as $sAttr ) {
42
+ if ( isset( $aOld[ $sAttr ] ) && isset( $aNew[ $sAttr ] ) && $aOld[ $sAttr ] != $aNew[ $sAttr ] ) {
43
+ $aChanged[ $nId ][] = $sAttr;
44
+ }
45
+ }
46
+ }
47
+
48
+ return array_filter( $aChanged );
49
+ }
50
+
51
+ /**
52
+ * @return array
53
+ */
54
+ protected function getCommonElements() {
55
+ return array_intersect_key( $this->getOldSnapshot(), $this->getNewSnapshot() );
56
+ }
57
+
58
+ /**
59
+ * @return array
60
+ */
61
+ protected function getRemoved() {
62
+ return array_diff_key( $this->getOldSnapshot(), $this->getNewSnapshot() );
63
+ }
64
+
65
+ /**
66
+ * @return string[]
67
+ */
68
+ protected function getAttributesToCompare() {
69
+ return [];
70
+ }
71
+ }
src/lib/src/ChangeTrack/Diff/DiffComments.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Diff;
4
+
5
+ class DiffComments extends Base {
6
+
7
+ /**
8
+ * @return string[]
9
+ */
10
+ protected function getAttributesToCompare() {
11
+ return [
12
+ 'post_id',
13
+ 'modified_at',
14
+ 'hash_content',
15
+ 'is_approved',
16
+ 'is_spam',
17
+ 'is_trash',
18
+ ];
19
+ }
20
+ }
src/lib/src/ChangeTrack/Diff/DiffMedia.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Diff;
4
+
5
+ class DiffMedia extends DiffPosts {
6
+ }
src/lib/src/ChangeTrack/Diff/DiffPages.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Diff;
4
+
5
+ class DiffPages extends DiffPosts {
6
+
7
+ /**
8
+ * @return string[]
9
+ */
10
+ protected function getAttributesToCompare() {
11
+ return array_merge(
12
+ parent::getAttributesToCompare(),
13
+ [ 'is_blog', 'is_front' ]
14
+ );
15
+ }
16
+ }
src/lib/src/ChangeTrack/Diff/DiffPlugins.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Diff;
4
+
5
+ class DiffPlugins extends Base {
6
+
7
+ /**
8
+ * @return string[]
9
+ */
10
+ protected function getAttributesToCompare() {
11
+ return [
12
+ 'name',
13
+ 'version',
14
+ 'is_active',
15
+ 'has_update',
16
+ ];
17
+ }
18
+ }
src/lib/src/ChangeTrack/Diff/DiffPosts.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Diff;
4
+
5
+ class DiffPosts extends Base {
6
+
7
+ /**
8
+ * @return string[]
9
+ */
10
+ protected function getAttributesToCompare() {
11
+ return [
12
+ 'slug',
13
+ 'modified_at',
14
+ 'hash_content',
15
+ 'hash_title',
16
+ ];
17
+ }
18
+ }
src/lib/src/ChangeTrack/Diff/DiffThemes.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Diff;
4
+
5
+ class DiffThemes extends Base {
6
+
7
+ /**
8
+ * @return string[]
9
+ */
10
+ protected function getAttributesToCompare() {
11
+ return [
12
+ 'name',
13
+ 'version',
14
+ 'is_active',
15
+ 'has_update',
16
+ 'is_child',
17
+ 'is_parent',
18
+ ];
19
+ }
20
+ }
src/lib/src/ChangeTrack/Diff/DiffUsers.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Diff;
4
+
5
+ class DiffUsers extends Base {
6
+
7
+ /**
8
+ * @return string[]
9
+ */
10
+ protected function getAttributesToCompare() {
11
+ return [
12
+ 'user_pass',
13
+ 'user_email',
14
+ 'is_admin',
15
+ ];
16
+ }
17
+ }
src/lib/src/ChangeTrack/Report/Build/Base.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Report\Build;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack;
6
+
7
+ class Base {
8
+
9
+ use ChangeTrack\Snapshot\SnapshotsConsumer;
10
+
11
+ public function run() {
12
+ $aDiff = ( new ChangeTrack\Diff\DiffUsers() )
13
+ ->setNewSnapshot( $this->getNewSnapshot() )
14
+ ->setOldSnapshot( $this->getOldSnapshot() )
15
+ ->run();
16
+
17
+ $bHasChanges = !empty( $aDiff[ 'added' ] ) && !empty( $aDiff[ 'removed' ] ) && !empty( $aDiff[ 'changed' ] );
18
+
19
+ if ( $bHasChanges ) {
20
+ $aAdded = $this->processAdded( $aDiff[ 'added' ] );
21
+ $aRemoved = $this->processRemoved( $aDiff[ 'removed' ] );
22
+ $aChanged = $this->processChanged( $aDiff[ 'changed' ] );
23
+ }
24
+ }
25
+
26
+ /**
27
+ * @param array $aAdded
28
+ * @return array
29
+ */
30
+ protected function processAdded( $aAdded ) {
31
+ $aReport = [];
32
+ if ( !empty( $aAdded ) ) {
33
+ $aReport[ 'title' ] = 'Items Added';
34
+ $aReport[ 'lines' ] = [];
35
+ foreach ( $aAdded as $aNew ) {
36
+ $aReport[ 'lines' ] = sprintf( 'New item added with unique ID "%s"', $aNew[ 'uniq' ] );
37
+ }
38
+ }
39
+ return $aReport;
40
+ }
41
+
42
+ /**
43
+ * @param array $aChanged
44
+ * @return array
45
+ */
46
+ protected function processChanged( $aChanged ) {
47
+ $aReport = [];
48
+ if ( !empty( $aChanged ) ) {
49
+ $aReport[ 'title' ] = 'Items Changed';
50
+ $aReport[ 'lines' ] = [];
51
+ foreach ( $aChanged as $sUniqId => $aAttributes ) {
52
+ $aReport[ 'lines' ] = sprintf(
53
+ 'The following attributes have changed on item with unique ID "%s": %s',
54
+ $aAttributes[ 'uniq' ], implode( ', ', $aAttributes ) );
55
+ }
56
+ }
57
+ return $aReport;
58
+ }
59
+
60
+ /**
61
+ * @param array $aRemoved
62
+ * @return array
63
+ */
64
+ protected function processRemoved( $aRemoved ) {
65
+ $aReport = [];
66
+ if ( !empty( $aRemoved ) ) {
67
+ $aReport[ 'title' ] = 'Items Removed';
68
+ $aReport[ 'lines' ] = [];
69
+ foreach ( $aRemoved as $aItem ) {
70
+ $aReport[ 'lines' ] = sprintf( 'Item removed with uniqud ID "%s"', $aItem[ 'uniq' ] );
71
+ }
72
+ }
73
+ return $aReport;
74
+ }
75
+ }
src/lib/src/ChangeTrack/Report/Build/Comments.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Report\Build;
4
+
5
+ class Comments extends Base {
6
+
7
+ /**
8
+ * @param array $aAdded
9
+ * @return array
10
+ */
11
+ protected function processAdded( $aAdded ) {
12
+ $aReport = [];
13
+ if ( !empty( $aAdded ) ) {
14
+ $aReport[ 'title' ] = 'New Comments';
15
+ $aReport[ 'lines' ] = [];
16
+ foreach ( $aAdded as $aItem ) {
17
+ $aReport[ 'lines' ] = sprintf( 'Comment Published ID:%s', $aItem[ 'uniq' ] );
18
+ }
19
+ }
20
+ return $aReport;
21
+ }
22
+
23
+ /**
24
+ * @param array $aChanged
25
+ * @return array
26
+ */
27
+ protected function processChanged( $aChanged ) {
28
+ $aReport = [];
29
+ if ( !empty( $aChanged ) ) {
30
+ $aReport[ 'title' ] = "Comments Changed";
31
+ $aReport[ 'lines' ] = [];
32
+ foreach ( $aChanged as $sUniqId => $aAttributes ) {
33
+ $aReport[ 'lines' ] = sprintf( 'Comment (ID:%s) changed attributes: %s',
34
+ $sUniqId, implode( ', ', $aAttributes ) );
35
+ }
36
+ }
37
+ return $aReport;
38
+ }
39
+
40
+ /**
41
+ * @param array $aRemoved
42
+ * @return array
43
+ */
44
+ protected function processRemoved( $aRemoved ) {
45
+ $aReport = [];
46
+ if ( !empty( $aRemoved ) ) {
47
+ $aReport[ 'title' ] = 'Comments Removed';
48
+ $aReport[ 'lines' ] = [];
49
+ foreach ( $aRemoved as $aItem ) {
50
+ $aReport[ 'lines' ] = sprintf( 'Comment Removed ID: %s', $aItem[ 'uniq' ] );
51
+ }
52
+ }
53
+ return $aReport;
54
+ }
55
+ }
src/lib/src/ChangeTrack/Report/Build/Media.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Report\Build;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ class Media extends Base {
8
+
9
+ /**
10
+ * @param array $aAdded
11
+ * @return array
12
+ */
13
+ protected function processAdded( $aAdded ) {
14
+ $aReport = [];
15
+ if ( !empty( $aAdded ) ) {
16
+ $aReport[ 'title' ] = 'Media Published';
17
+ $aReport[ 'lines' ] = [];
18
+ foreach ( $aAdded as $aItem ) {
19
+ $aReport[ 'lines' ] = sprintf( 'Media added (slug:%s): "%s"', $aItem[ 'slug' ], $aItem[ 'title' ] );
20
+ }
21
+ }
22
+ return $aReport;
23
+ }
24
+
25
+ /**
26
+ * @param array $aChanged
27
+ * @return array
28
+ */
29
+ protected function processChanged( $aChanged ) {
30
+ $aReport = [];
31
+ if ( !empty( $aChanged ) ) {
32
+ $aReport[ 'title' ] = "Media Changed";
33
+ $aReport[ 'lines' ] = [];
34
+ foreach ( $aChanged as $sUniqId => $aAttributes ) {
35
+ $aReport[ 'lines' ] = sprintf( 'Media change (ID:%s) changed attributes: %s',
36
+ $sUniqId, implode( ', ', $aAttributes ) );
37
+ }
38
+ }
39
+ return $aReport;
40
+ }
41
+
42
+ /**
43
+ * @param array $aRemoved
44
+ * @return array
45
+ */
46
+ protected function processRemoved( $aRemoved ) {
47
+ $aReport = [];
48
+ if ( !empty( $aRemoved ) ) {
49
+ $aReport[ 'title' ] = 'Media Removed';
50
+ $aReport[ 'lines' ] = [];
51
+ foreach ( $aRemoved as $aItem ) {
52
+ $aReport[ 'lines' ] = sprintf( 'Media removed (slug:%s): "%s"', $aItem[ 'slug' ], $aItem[ 'title' ] );
53
+ }
54
+ }
55
+ return $aReport;
56
+ }
57
+ }
src/lib/src/ChangeTrack/Report/Build/Pages.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Report\Build;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ class Pages extends Base {
8
+
9
+ /**
10
+ * @param array $aAdded
11
+ * @return array
12
+ */
13
+ protected function processAdded( $aAdded ) {
14
+ $aReport = [];
15
+ if ( !empty( $aAdded ) ) {
16
+ $aReport[ 'title' ] = 'Pages Published';
17
+ $aReport[ 'lines' ] = [];
18
+ $oWpPosts = Services::WpPost();
19
+ foreach ( $aAdded as $aItem ) {
20
+ $oItem = $oWpPosts->getById( $aItem[ 'uniq' ] );
21
+ $aReport[ 'lines' ] = sprintf( 'Page Published (slug:%s): "%s"', $oItem->post_name, $oItem->post_title );
22
+ }
23
+ }
24
+ return $aReport;
25
+ }
26
+
27
+ /**
28
+ * @param array $aChanged
29
+ * @return array
30
+ */
31
+ protected function processChanged( $aChanged ) {
32
+ $aReport = [];
33
+ if ( !empty( $aChanged ) ) {
34
+ $aReport[ 'title' ] = "Pages Changed";
35
+ $aReport[ 'lines' ] = [];
36
+ $oWpPosts = Services::WpPost();
37
+ foreach ( $aChanged as $sUniqId => $aAttributes ) {
38
+ $oItem = $oWpPosts->getById( $sUniqId );
39
+ $aReport[ 'lines' ] = sprintf( 'Page "%s" (slug:%s) changed attributes: %s',
40
+ $oItem->post_title, $oItem->post_name, implode( ', ', $aAttributes ) );
41
+ }
42
+ }
43
+ return $aReport;
44
+ }
45
+
46
+ /**
47
+ * @param array $aRemoved
48
+ * @return array
49
+ */
50
+ protected function processRemoved( $aRemoved ) {
51
+ $aReport = [];
52
+ if ( !empty( $aRemoved ) ) {
53
+ $aReport[ 'title' ] = 'Pages Removed';
54
+ $aReport[ 'lines' ] = [];
55
+ foreach ( $aRemoved as $aItem ) {
56
+ $aReport[ 'lines' ] = sprintf( 'Page Un-Published (slug:%s): "%s"', $aItem[ 'slug' ], $aItem[ 'title' ] );
57
+ }
58
+ }
59
+ return $aReport;
60
+ }
61
+ }
src/lib/src/ChangeTrack/Report/Build/Plugins.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Report\Build;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ class Plugins extends Base {
8
+
9
+ /**
10
+ * @param array $aAdded
11
+ * @return array
12
+ */
13
+ protected function processAdded( $aAdded ) {
14
+ $aReport = [];
15
+ if ( !empty( $aAdded ) ) {
16
+ $aReport[ 'title' ] = 'Plugins Installed';
17
+ $aReport[ 'lines' ] = [];
18
+ $oWpPlugins = Services::WpPlugins();
19
+ foreach ( $aAdded as $aItem ) {
20
+ $oPlugin = $oWpPlugins->getPluginAsVo( $aItem[ 'uniq' ] );
21
+ $aReport[ 'lines' ] = sprintf( 'Plugin added (file:%s): "%s"', $oPlugin->file, $oPlugin->Name );
22
+ }
23
+ }
24
+ return $aReport;
25
+ }
26
+
27
+ /**
28
+ * @param array $aChanged
29
+ * @return array
30
+ */
31
+ protected function processChanged( $aChanged ) {
32
+ $aReport = [];
33
+ if ( !empty( $aChanged ) ) {
34
+ $aReport[ 'title' ] = "Plugins Changed";
35
+ $aReport[ 'lines' ] = [];
36
+ $oWpPlugins = Services::WpPlugins();
37
+ foreach ( $aChanged as $sUniqId => $aAttributes ) {
38
+ $oItem = $oWpPlugins->getPluginAsVo( $sUniqId );
39
+ $aReport[ 'lines' ] = sprintf( 'Plugin "%s" (file:%s) changed attributes: %s',
40
+ $oItem->Name, $sUniqId, implode( ', ', $aAttributes ) );
41
+ }
42
+ }
43
+ return $aReport;
44
+ }
45
+
46
+ /**
47
+ * @param array $aRemoved
48
+ * @return array
49
+ */
50
+ protected function processRemoved( $aRemoved ) {
51
+ $aReport = [];
52
+ if ( !empty( $aRemoved ) ) {
53
+ $aReport[ 'title' ] = 'Plugins Removed';
54
+ $aReport[ 'lines' ] = [];
55
+ foreach ( $aRemoved as $aItem ) {
56
+ $aReport[ 'lines' ] = sprintf( 'Plugin removed (file:%s): "%s"', $aItem[ 'uniq' ], $aItem[ 'name' ] );
57
+ }
58
+ }
59
+ return $aReport;
60
+ }
61
+ }
src/lib/src/ChangeTrack/Report/Build/Posts.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Report\Build;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ class Posts extends Base {
8
+
9
+ /**
10
+ * @param array $aAdded
11
+ * @return array
12
+ */
13
+ protected function processAdded( $aAdded ) {
14
+ $aReport = [];
15
+ if ( !empty( $aAdded ) ) {
16
+ $aReport[ 'title' ] = 'Posts Published';
17
+ $aReport[ 'lines' ] = [];
18
+ $oWpPosts = Services::WpPost();
19
+ foreach ( $aAdded as $aItem ) {
20
+ $oItem = $oWpPosts->getById( $aItem[ 'uniq' ] );
21
+ $aReport[ 'lines' ] = sprintf( 'Post Published (slug:%s): "%s"', $oItem->post_name, $oItem->post_title );
22
+ }
23
+ }
24
+ return $aReport;
25
+ }
26
+
27
+ /**
28
+ * @param array $aChanged
29
+ * @return array
30
+ */
31
+ protected function processChanged( $aChanged ) {
32
+ $aReport = [];
33
+ if ( !empty( $aChanged ) ) {
34
+ $aReport[ 'title' ] = "Posts Changed";
35
+ $aReport[ 'lines' ] = [];
36
+ $oWpPosts = Services::WpPost();
37
+ foreach ( $aChanged as $sUniqId => $aAttributes ) {
38
+ $oItem = $oWpPosts->getById( $sUniqId );
39
+ $aReport[ 'lines' ] = sprintf( 'Post "%s" (slug:%s) changed attributes: %s',
40
+ $oItem->post_title, $oItem->post_name, implode( ', ', $aAttributes ) );
41
+ }
42
+ }
43
+ return $aReport;
44
+ }
45
+
46
+ /**
47
+ * @param array $aRemoved
48
+ * @return array
49
+ */
50
+ protected function processRemoved( $aRemoved ) {
51
+ $aReport = [];
52
+ if ( !empty( $aRemoved ) ) {
53
+ $aReport[ 'title' ] = 'Posts Removed';
54
+ $aReport[ 'lines' ] = [];
55
+ foreach ( $aRemoved as $aItem ) {
56
+ $aReport[ 'lines' ] = sprintf( 'Post Un-Published (slug:%s): "%s"', $aItem[ 'slug' ], $aItem[ 'title' ] );
57
+ }
58
+ }
59
+ return $aReport;
60
+ }
61
+ }
src/lib/src/ChangeTrack/Report/Build/Themes.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Report\Build;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ class Themes extends Base {
8
+
9
+ /**
10
+ * @param array $aAdded
11
+ * @return array
12
+ */
13
+ protected function processAdded( $aAdded ) {
14
+ $aReport = [];
15
+ if ( !empty( $aAdded ) ) {
16
+ $aReport[ 'title' ] = 'Themes Installed';
17
+ $aReport[ 'lines' ] = [];
18
+ $oWpThemes = Services::WpThemes();
19
+ foreach ( $aAdded as $aItem ) {
20
+ $oItem = $oWpThemes->getTheme( $aItem[ 'uniq' ] );
21
+ $aReport[ 'lines' ] = sprintf( 'Theme added (dir:%s): "%s"', $oItem->get_stylesheet(), $oItem->get( 'Name' ) );
22
+ }
23
+ }
24
+ return $aReport;
25
+ }
26
+
27
+ /**
28
+ * @param array $aChanged
29
+ * @return array
30
+ */
31
+ protected function processChanged( $aChanged ) {
32
+ $aReport = [];
33
+ if ( !empty( $aChanged ) ) {
34
+ $aReport[ 'title' ] = "Themes Changed";
35
+ $aReport[ 'lines' ] = [];
36
+ $oWpThemes = Services::WpThemes();
37
+ foreach ( $aChanged as $sUniqId => $aAttributes ) {
38
+ $oItem = $oWpThemes->getTheme( $sUniqId );
39
+ $aReport[ 'lines' ] = sprintf( 'Theme "%s" (dir:%s) changed attributes: %s',
40
+ $oItem->get( 'Name' ), $oItem->get_stylesheet(), implode( ', ', $aAttributes ) );
41
+ }
42
+ }
43
+ return $aReport;
44
+ }
45
+
46
+ /**
47
+ * @param array $aRemoved
48
+ * @return array
49
+ */
50
+ protected function processRemoved( $aRemoved ) {
51
+ $aReport = [];
52
+ if ( !empty( $aRemoved ) ) {
53
+ $aReport[ 'title' ] = 'Themes Removed';
54
+ $aReport[ 'lines' ] = [];
55
+ foreach ( $aRemoved as $aItem ) {
56
+ $aReport[ 'lines' ] = sprintf( 'Theme removed (dir:%s): "%s"', $aItem[ 'uniq' ], $aItem[ 'name' ] );
57
+ }
58
+ }
59
+ return $aReport;
60
+ }
61
+ }
src/lib/src/ChangeTrack/Report/Build/Users.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Report\Build;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ class Users extends Base {
8
+
9
+ /**
10
+ * @param array $aAdded
11
+ * @return array
12
+ */
13
+ protected function processAdded( $aAdded ) {
14
+ $aReport = [];
15
+ if ( !empty( $aAdded ) ) {
16
+ $aReport[ 'title' ] = 'Users Created';
17
+ $aReport[ 'lines' ] = [];
18
+ foreach ( $aAdded as $aItem ) {
19
+ $aReport[ 'lines' ] = sprintf( 'New user added with ID %s and username "%s"', $aItem[ 'uniq' ], $aItem[ 'user_login' ] );
20
+ }
21
+ }
22
+ return $aReport;
23
+ }
24
+
25
+ /**
26
+ * @param array $aChanged
27
+ * @return array
28
+ */
29
+ protected function processChanged( $aChanged ) {
30
+ $aReport = [];
31
+ if ( !empty( $aChanged ) ) {
32
+ $oWpUsers = Services::WpUsers();
33
+ $aReport[ 'title' ] = "Users Changed";
34
+ $aReport[ 'lines' ] = [];
35
+ foreach ( $aChanged as $sUniqId => $aAttributes ) {
36
+ $aReport[ 'lines' ] = sprintf( 'User "%s" (ID:%s) changed attributes: %s',
37
+ $oWpUsers->getUserById( $sUniqId )->user_login, $sUniqId, implode( ', ', $aAttributes ) );
38
+ }
39
+ }
40
+ return $aReport;
41
+ }
42
+
43
+ /**
44
+ * @param array $aRemoved
45
+ * @return array
46
+ */
47
+ protected function processRemoved( $aRemoved ) {
48
+ $aReport = [];
49
+ if ( !empty( $aRemoved ) ) {
50
+ $aReport[ 'title' ] = 'Users Removed';
51
+ $aReport[ 'lines' ] = [];
52
+ foreach ( $aRemoved as $aItem ) {
53
+ $aReport[ 'lines' ] = sprintf( 'User removed with ID %s and username "%s"', $aItem[ 'uniq' ], $aItem[ 'user_login' ] );
54
+ }
55
+ }
56
+ return $aReport;
57
+ }
58
+ }
src/lib/src/ChangeTrack/Snapshot/BuildComments.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ /**
8
+ * Class BuildComments
9
+ * @package FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot
10
+ */
11
+ class BuildComments {
12
+
13
+ /**
14
+ * @return array[]
15
+ */
16
+ public function run() {
17
+ return $this->retrieve();
18
+ }
19
+
20
+ /**
21
+ * @param array $aParams
22
+ * @return array[]
23
+ */
24
+ protected function retrieve( $aParams = [] ) {
25
+ $aActual = [];
26
+
27
+ $aParams = Services::DataManipulation()->mergeArraysRecursive( $this->getBaseParameters(), $aParams );
28
+ $nPage = 0;
29
+ do {
30
+ $aParams[ 'offset' ] = $aParams[ 'number' ]*$nPage++;
31
+ /** @var \WP_Comment[] $aQueryResult */
32
+ $aQueryResult = get_comments( $aParams );
33
+ if ( is_array( $aQueryResult ) ) {
34
+ foreach ( $aQueryResult as $oComment ) {
35
+ $aActual[ $oComment->comment_ID ] = [
36
+ 'uniq' => $oComment->comment_ID,
37
+ 'post_id' => $oComment->comment_post_ID,
38
+ 'modified_at' => strtotime( $oComment->comment_date_gmt ),
39
+ 'hash_content' => sha1( $oComment->comment_content ),
40
+ 'is_approved' => $oComment->comment_approved === '1',
41
+ 'is_spam' => $oComment->comment_approved === 'spam',
42
+ 'is_trash' => $oComment->comment_approved === 'trash',
43
+ ];
44
+ }
45
+ }
46
+
47
+ $nPage++;
48
+ } while ( !empty( $aQueryResult ) );
49
+
50
+ return $aActual;
51
+ }
52
+
53
+ /**
54
+ * @return array
55
+ */
56
+ protected function getBaseParameters() {
57
+ return [
58
+ 'number' => 20,
59
+ 'status' => 'all,spam,trash'
60
+ ];
61
+ }
62
+ }
src/lib/src/ChangeTrack/Snapshot/BuildMedia.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot;
4
+
5
+ /**
6
+ * Class BuildMedia
7
+ * @package FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot
8
+ */
9
+ class BuildMedia extends BuildPosts {
10
+
11
+ /**
12
+ * @param array $aParams
13
+ * @return array[]
14
+ */
15
+ protected function retrieve( $aParams = [] ) {
16
+ return parent::retrieve( $aParams );
17
+ }
18
+
19
+ /**
20
+ * @return array
21
+ */
22
+ protected function getBaseParameters() {
23
+ $aParams = parent::getBaseParameters();
24
+ $aParams[ 'post_type' ] = 'attachment';
25
+ unset( $aParams[ 'post_status' ] );
26
+ return $aParams;
27
+ }
28
+ }
src/lib/src/ChangeTrack/Snapshot/BuildPages.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot;
4
+
5
+ /**
6
+ * Class BuildPages
7
+ * @package FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot
8
+ */
9
+ class BuildPages extends BuildPosts {
10
+
11
+ /**
12
+ * @param array $aParams
13
+ * @return array[]
14
+ */
15
+ protected function retrieve( $aParams = [] ) {
16
+ $aItems = parent::retrieve( $aParams );
17
+
18
+ $nBlogId = (int)get_option( 'page_for_posts' );
19
+ $nFrontId = (int)get_option( 'page_on_front' );
20
+ foreach ( $aItems as &$aItem ) {
21
+ $aItem[ 'is_blog' ] = ( $nBlogId == $aItem[ 'uniq' ] );
22
+ $aItem[ 'is_front' ] = ( $nFrontId == $aItem[ 'uniq' ] );
23
+ }
24
+
25
+ return $aItems;
26
+ }
27
+
28
+ /**
29
+ * @return array
30
+ */
31
+ protected function getBaseParameters() {
32
+ $aParams = parent::getBaseParameters();
33
+ $aParams[ 'post_type' ] = 'page';
34
+ return $aParams;
35
+ }
36
+ }
src/lib/src/ChangeTrack/Snapshot/BuildPlugins.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ /**
8
+ * Class BuildPlugins
9
+ * @package FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot
10
+ */
11
+ class BuildPlugins {
12
+
13
+ /**
14
+ * @return array[] - key is plugin file, values are arrays with keys: file, version, is_active, has_updates
15
+ */
16
+ public function run() {
17
+ return $this->getItems();
18
+ }
19
+
20
+ /**
21
+ * @return array
22
+ */
23
+ private function getItems() {
24
+ $aItems = [];
25
+ foreach ( Services::WpPlugins()->getPluginsAsVo() as $sFile => $oPlugin ) {
26
+ $aItems[ $sFile ] = [
27
+ 'uniq' => $sFile,
28
+ 'name' => $oPlugin->Name,
29
+ 'version' => $oPlugin->Version,
30
+ 'is_active' => $oPlugin->active,
31
+ 'has_update' => $oPlugin->hasUpdate(),
32
+ ];
33
+ }
34
+ return $aItems;
35
+ }
36
+ }
src/lib/src/ChangeTrack/Snapshot/BuildPosts.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ /**
8
+ * Class BuildPosts
9
+ * @package FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot
10
+ */
11
+ class BuildPosts {
12
+
13
+ /**
14
+ * @return array[] - key is user ID, values are arrays with keys: id, user_login, user_pass, user_email, is_admin
15
+ */
16
+ public function run() {
17
+ return $this->retrieve();
18
+ }
19
+
20
+ /**
21
+ * @param array $aParams
22
+ * @return array[]
23
+ */
24
+ protected function retrieve( $aParams = [] ) {
25
+ $aActual = [];
26
+
27
+ $aParams = Services::DataManipulation()->mergeArraysRecursive( $this->getBaseParameters(), $aParams );
28
+
29
+ do {
30
+ /** @var \WP_Post[] $aQueryResult */
31
+ $aQueryResult = get_posts( $aParams );
32
+ if ( is_array( $aQueryResult ) ) {
33
+ foreach ( $aQueryResult as $oPost ) {
34
+ $aActual[ $oPost->ID ] = [
35
+ 'uniq' => $oPost->ID,
36
+ 'slug' => $oPost->post_name,
37
+ 'title' => $oPost->post_title,
38
+ 'modified_at' => strtotime( $oPost->post_date_gmt ),
39
+ 'hash_content' => sha1( $oPost->post_content ),
40
+ 'hash_title' => sha1( $oPost->post_title ),
41
+ ];
42
+ }
43
+ }
44
+
45
+ $aParams[ 'paged' ]++;
46
+ } while ( !empty( $aQueryResult ) );
47
+
48
+ return $aActual;
49
+ }
50
+
51
+ /**
52
+ * @return array
53
+ */
54
+ protected function getBaseParameters() {
55
+ return [
56
+ 'numberposts' => 10,
57
+ 'post_status' => 'publish',
58
+ 'paged' => 1,
59
+ 'post_type' => 'post',
60
+ ];
61
+ }
62
+ }
src/lib/src/ChangeTrack/Snapshot/BuildThemes.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ /**
8
+ * Class BuildThemes
9
+ * @package FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot
10
+ */
11
+ class BuildThemes {
12
+
13
+ /**
14
+ * @return array[] - key is plugin file, values are arrays with keys: file, version, is_active, has_updates
15
+ */
16
+ public function run() {
17
+ return $this->getItems();
18
+ }
19
+
20
+ /**
21
+ * @return array
22
+ */
23
+ private function getItems() {
24
+ $oWp = Services::WpThemes();
25
+ $aItems = [];
26
+ foreach ( $oWp->getThemes() as $oItem ) {
27
+ $sFile = $oItem->get_stylesheet();
28
+ $bActive = $oWp->isActive( $sFile );
29
+ $aItems[ $sFile ] = [
30
+ 'uniq' => $sFile,
31
+ 'name' => $oItem->get( 'Name' ),
32
+ 'version' => $oItem->get( 'Version' ),
33
+ 'has_update' => $oWp->isUpdateAvailable( $sFile ),
34
+ 'is_active' => $bActive,
35
+ 'is_child' => $bActive && $oWp->isActiveThemeAChild(),
36
+ 'is_parent' => !$bActive && $oWp->isActiveParent( $sFile ),
37
+ ];
38
+ }
39
+ return $aItems;
40
+ }
41
+ }
src/lib/src/ChangeTrack/Snapshot/BuildUsers.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ /**
8
+ * Class BuildUsers
9
+ * @package FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot
10
+ */
11
+ class BuildUsers {
12
+
13
+ /**
14
+ * @uses 2 SQL queries
15
+ * @return array[] - key is user ID, values are arrays with keys: id, user_login, user_pass, user_email, is_admin
16
+ */
17
+ public function run() {
18
+ $aAdminIds = array_keys( $this->getAdmins() );
19
+ return array_map(
20
+ function ( $aUser ) use ( $aAdminIds ) {
21
+ $aUser[ 'is_admin' ] = in_array( $aUser[ 'uniq' ], $aAdminIds );
22
+ return $aUser;
23
+ },
24
+ $this->getUsers()
25
+ );
26
+ }
27
+
28
+ /**
29
+ * @return array
30
+ */
31
+ private function getAdmins() {
32
+ return $this->getUsers( [ 'role' => 'administrator' ] );
33
+ }
34
+
35
+ /**
36
+ * @param array $aParams
37
+ * @return array[]
38
+ */
39
+ private function getUsers( $aParams = [] ) {
40
+ $aParams = Services::DataManipulation()->mergeArraysRecursive(
41
+ [
42
+ 'fields' => $this->getFields(),
43
+ 'number' => 1,
44
+ 'paged' => 1,
45
+ ],
46
+ $aParams
47
+ );
48
+
49
+ $aActual = [];
50
+ do {
51
+ $aUserResult = Services::WpUsers()->getAllUsers( $aParams );
52
+ foreach ( $aUserResult as $oUser ) {
53
+ /** @var \stdClass $oUser */
54
+ $aActual[ $oUser->id ] = [
55
+ 'uniq' => $oUser->id,
56
+ 'user_pass' => sha1( $oUser->user_pass ),
57
+ 'user_email' => sha1( $oUser->user_email ),
58
+ ];
59
+ }
60
+ $aParams[ 'paged' ]++;
61
+ } while ( !empty( $aUserResult ) );
62
+
63
+ return $aActual;
64
+ }
65
+
66
+ /**
67
+ * @return array
68
+ */
69
+ private function getFields() {
70
+ return [
71
+ 'id',
72
+ 'user_pass',
73
+ 'user_email',
74
+ ];
75
+ }
76
+ }
src/lib/src/ChangeTrack/Snapshot/Collate.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ /**
8
+ * Class Collate
9
+ * @package FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot
10
+ */
11
+ class Collate {
12
+
13
+ /**
14
+ * @return array
15
+ */
16
+ public function run() {
17
+ return [
18
+ 'users' => ( new BuildUsers() )->run(),
19
+ 'post' => ( new BuildPosts() )->run(),
20
+ 'pages' => ( new BuildPages() )->run(),
21
+ 'plugins' => ( new BuildPlugins() )->run(),
22
+ 'themes' => ( new BuildThemes() )->run(),
23
+ 'comments' => ( new BuildComments() )->run(),
24
+ 'media' => ( new BuildMedia() )->run(),
25
+ ];
26
+ }
27
+ }
src/lib/src/ChangeTrack/Snapshot/SnapshotsConsumer.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\ChangeTrack\Snapshot;
4
+
5
+ trait SnapshotsConsumer {
6
+
7
+ /**
8
+ * @var array
9
+ */
10
+ private $aOldSnapshot;
11
+
12
+ /**
13
+ * @var array
14
+ */
15
+ private $aNewSnapshot;
16
+
17
+ /**
18
+ * @return array
19
+ */
20
+ public function getOldSnapshot() {
21
+ return $this->aOldSnapshot;
22
+ }
23
+
24
+ /**
25
+ * @param array $aSnapshot
26
+ * @return $this
27
+ */
28
+ public function setOldSnapshot( $aSnapshot ) {
29
+ $this->aOldSnapshot = $this->structureSnapshotItems( $aSnapshot );
30
+ return $this;
31
+ }
32
+
33
+ /**
34
+ * @return array
35
+ */
36
+ public function getNewSnapshot() {
37
+ return $this->aNewSnapshot;
38
+ }
39
+
40
+ /**
41
+ * @param array $aSnapshot
42
+ * @return $this
43
+ */
44
+ public function setNewSnapshot( $aSnapshot ) {
45
+ $this->aNewSnapshot = $this->structureSnapshotItems( $aSnapshot );
46
+ return $this;
47
+ }
48
+
49
+ /**
50
+ * Ensures that the items in the snapshot array have keys that correspond to their uniq IDs.
51
+ * @param array[] $aSnapshotItems
52
+ * @return array[]
53
+ */
54
+ private function structureSnapshotItems( $aSnapshotItems ) {
55
+ $aStructured = [];
56
+ foreach ( $aSnapshotItems as $aItem ) {
57
+ $aStructured[ $aItem[ 'uniq' ] ] = $aItem;
58
+ }
59
+ return $aStructured;
60
+ }
61
+
62
+ }
src/lib/src/Databases/ChangeTracking/Delete.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\ChangeTracking;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
+
7
+ class Delete extends Base\Delete {
8
+ }
src/lib/src/Databases/ChangeTracking/EntryVO.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\ChangeTracking;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
+
7
+ /**
8
+ * Class EntryVO
9
+ *
10
+ * @property string ip
11
+ * @property array data
12
+ * @property array meta
13
+ */
14
+ class EntryVO extends Base\EntryVO {
15
+
16
+ /**
17
+ * @param string $sProperty
18
+ * @return mixed
19
+ */
20
+ public function __get( $sProperty ) {
21
+
22
+ $mVal = parent::__get( $sProperty );
23
+
24
+ switch ( $sProperty ) {
25
+
26
+ case 'data':
27
+ $mVal = json_decode( \WP_Http_Encoding::decompress( $mVal ), true );
28
+ break;
29
+
30
+ default:
31
+ break;
32
+ }
33
+
34
+ return $mVal;
35
+ }
36
+
37
+ /**
38
+ * @param string $sProperty
39
+ * @param mixed $mValue
40
+ * @return $this|mixed
41
+ */
42
+ public function __set( $sProperty, $mValue ) {
43
+
44
+ switch ( $sProperty ) {
45
+
46
+ case 'data':
47
+ $mValue = \WP_Http_Encoding::compress( json_encode( $mValue ) );
48
+ break;
49
+
50
+ default:
51
+ break;
52
+ }
53
+
54
+ return parent::__set( $sProperty, $mValue );
55
+ }
56
+ }
src/lib/src/Databases/ChangeTracking/Handler.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\ChangeTracking;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
+
7
+ class Handler extends Base\Handler {
8
+ }
src/lib/src/Databases/ChangeTracking/Insert.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\ChangeTracking;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class Insert extends Base\Insert {
9
+
10
+ /**
11
+ * @return array
12
+ */
13
+ public function getInsertData() {
14
+ $aInsert = parent::getInsertData();
15
+ // $aInsert[ 'data' ] = \WP_Http_Encoding::compress( json_encode( $aInsert[ 'data' ] ) );
16
+ return $aInsert;
17
+ }
18
+ }
src/lib/src/Databases/ChangeTracking/Select.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\ChangeTracking;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class Select extends Base\Select {
9
+ }
src/lib/src/Databases/ChangeTracking/Update.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Databases\ChangeTracking;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Databases\Base;
6
+
7
+ class Update extends Base\Update {
8
+ }
src/lib/src/Modules/MouseTrap/Base.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\MouseTrap;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ abstract class Base {
9
+
10
+ use Shield\AuditTrail\Auditor,
11
+ Shield\Modules\ModConsumer;
12
+
13
+ public function run() {
14
+ add_action( 'init', [ $this, 'onWpInit' ] );
15
+ }
16
+
17
+ public function onWpInit() {
18
+ if ( !Services::WpUsers()->isUserLoggedIn() ) {
19
+ $this->process();
20
+ }
21
+ }
22
+
23
+ protected function process() {
24
+ }
25
+
26
+ protected function doTransgression() {
27
+ /** @var \ICWP_WPSF_FeatureHandler_Mousetrap $oFO */
28
+ $oFO = $this->getMod();
29
+ if ( !$oFO->isVerifiedBot() ) {
30
+ $this->isTransgression() ? $oFO->setIpTransgressed() : $oFO->setIpBlocked();
31
+ $this->writeAudit();
32
+ }
33
+ }
34
+
35
+ /**
36
+ * @return bool
37
+ */
38
+ abstract protected function isTransgression();
39
+
40
+ /**
41
+ * @return $this
42
+ */
43
+ abstract protected function writeAudit();
44
+ }
src/lib/src/Modules/MouseTrap/Detect404.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\MouseTrap;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ class Detect404 extends Base {
8
+
9
+ protected function process() {
10
+ add_action( 'template_redirect', function () {
11
+ if ( is_404() ) {
12
+ $this->doTransgression();
13
+ }
14
+ } );
15
+ }
16
+
17
+ protected function isTransgression() {
18
+ /** @var \ICWP_WPSF_FeatureHandler_Mousetrap $oFO */
19
+ $oFO = $this->getMod();
20
+ return $oFO->isTransgression404();
21
+ }
22
+
23
+ /**
24
+ * @return $this
25
+ */
26
+ protected function writeAudit() {
27
+ $this->createNewAudit(
28
+ 'wpsf',
29
+ sprintf( _wpsf__( '404 detected at "%s"' ), Services::Request()->getPath() ),
30
+ 2, 'mousetrap_404'
31
+ );
32
+ return $this;
33
+ }
34
+ }
src/lib/src/Modules/MouseTrap/DetectXmlRpc.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\MouseTrap;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ class DetectXmlRpc extends Base {
8
+
9
+ protected function process() {
10
+ if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST
11
+ || preg_match( '#/xmlrpc\.php#', Services::Request()->getPath() ) ) {
12
+ $this->doTransgression();
13
+ }
14
+ }
15
+
16
+ /**
17
+ * @return bool
18
+ */
19
+ protected function isTransgression() {
20
+ /** @var \ICWP_WPSF_FeatureHandler_Mousetrap $oFO */
21
+ $oFO = $this->getMod();
22
+ return $oFO->isTransgressionXmlRpc();
23
+ }
24
+
25
+ /**
26
+ * @return $this
27
+ */
28
+ protected function writeAudit() {
29
+ $this->createNewAudit(
30
+ 'wpsf',
31
+ sprintf( _wpsf__( 'Attempt to access XML-RPC detected at "%s"' ), Services::Request()->getPath() ),
32
+ 2, 'mousetrap_xmlrpc'
33
+ );
34
+ return $this;
35
+ }
36
+ }
src/lib/src/Modules/MouseTrap/FakeWebCrawler.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\MouseTrap;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ /**
8
+ * Class FakeWebCrawler
9
+ * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\MouseTrap
10
+ */
11
+ class FakeWebCrawler extends Base {
12
+
13
+ protected function process() {
14
+ try {
15
+ $this->getIfVisitorIdentifiesAsCrawler(); // TEST this logic
16
+ }
17
+ catch ( \Exception $oE ) {
18
+ $this->doTransgression();
19
+ }
20
+ }
21
+
22
+ /**
23
+ * @return bool
24
+ */
25
+ protected function isTransgression() {
26
+ /** @var \ICWP_WPSF_FeatureHandler_Mousetrap $oFO */
27
+ $oFO = $this->getMod();
28
+ return $oFO->isTransgressionFakeWebCrawler();
29
+ }
30
+
31
+ /**
32
+ * @return $this
33
+ */
34
+ protected function writeAudit() {
35
+ $this->createNewAudit(
36
+ 'wpsf',
37
+ sprintf( _wpsf__( 'Fake Web Crawler detected "%s"' ), Services::Request()->getPath() ),
38
+ 2, 'mousetrap_fakecrawler'
39
+ );
40
+ return $this;
41
+ }
42
+
43
+ /**
44
+ * @return false
45
+ * @throws \Exception
46
+ */
47
+ private function getIfVisitorIdentifiesAsCrawler() {
48
+ $bIdentifiesAs = false;
49
+
50
+ $sUserAgent = Services::Request()->getUserAgent();
51
+ if ( !empty( $sUserAgent ) ) {
52
+ foreach ( Services::ServiceProviders()->getAllCrawlerUseragents() as $sPossibleAgent ) {
53
+ if ( stripos( $sUserAgent, $sPossibleAgent ) !== false ) {
54
+ throw new \Exception( $sPossibleAgent );
55
+ break;
56
+ }
57
+ }
58
+ }
59
+
60
+ return $bIdentifiesAs;
61
+ }
62
+ }
src/lib/src/Modules/MouseTrap/InvalidUsername.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\MouseTrap;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ class InvalidUsername extends Base {
8
+
9
+ protected function process() {
10
+ add_filter( 'authenticate',
11
+ /**
12
+ * @param null|\WP_User|\WP_Error $oUser
13
+ * @param $sUsernameEmail
14
+ * @return null|\WP_User|\WP_Error
15
+ */
16
+ function ( $oUser, $sUsernameEmail ) {
17
+ if ( !empty( $sUsernameEmail ) && !$this->userExists( $sUsernameEmail ) ) {
18
+ $this->doTransgression();
19
+ }
20
+ return $oUser;
21
+ },
22
+ 5, 2 );
23
+ }
24
+
25
+ /**
26
+ * @return bool
27
+ */
28
+ protected function isTransgression() {
29
+ /** @var \ICWP_WPSF_FeatureHandler_Mousetrap $oFO */
30
+ $oFO = $this->getMod();
31
+ return $oFO->isTransgressionInvalidUsernames();
32
+ }
33
+
34
+ /**
35
+ * @return $this
36
+ */
37
+ protected function writeAudit() {
38
+ $this->createNewAudit(
39
+ 'wpsf',
40
+ sprintf( _wpsf__( 'Attempted login by invalid username "%s"' ), Services::Request()->getPath() ),
41
+ 2, 'mousetrap_invaliduser'
42
+ );
43
+ return $this;
44
+ }
45
+
46
+ /**
47
+ * @param string $sUsernameEmail
48
+ * @return bool
49
+ */
50
+ private function userExists( $sUsernameEmail ) {
51
+ $oWpUsers = Services::WpUsers();
52
+ return ( $oWpUsers->getUserByEmail( $sUsernameEmail ) instanceof \WP_User )
53
+ || ( $oWpUsers->getUserByUsername( $sUsernameEmail ) instanceof \WP_User );
54
+ }
55
+ }
src/lib/src/Modules/MouseTrap/LinkCheese.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\MouseTrap;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ /**
9
+ * Works by inserting a random, nofollow link to the footer of the page and appending to robots.txt
10
+ * Class LinkCheese
11
+ * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\MouseTrap
12
+ */
13
+ class LinkCheese extends Base {
14
+
15
+ protected function process() {
16
+ if ( $this->isCheese() ) {
17
+ $this->doTransgression();
18
+ }
19
+ add_filter( 'robots_txt', array( $this, 'appendRobotsTxt' ), 5 );
20
+ add_action( 'wp_footer', array( $this, 'insertMouseTrap' ) );
21
+ }
22
+
23
+ /**
24
+ * @param string $sRobotsText
25
+ * @return string
26
+ */
27
+ public function appendRobotsTxt( $sRobotsText ) {
28
+ $sTempl = Services::WpGeneral()->isPermalinksEnabled() ? "Disallow: /%s-*/\n" : "Disallow: /*?*%s=\n";
29
+ $sRobotsText = rtrim( $sRobotsText, "\n" )."\n";
30
+ foreach ( $this->getPossibleWords() as $sWord ) {
31
+ $sRobotsText .= sprintf( $sTempl, $this->getMod()->prefix( $sWord ) );
32
+ }
33
+ return $sRobotsText;
34
+ }
35
+
36
+ private function isCheese() {
37
+ /** @var \ICWP_WPSF_FeatureHandler_Mousetrap $oFO */
38
+ $oFO = $this->getMod();
39
+ $oReq = Services::Request();
40
+
41
+ $bIsCheese = false;
42
+ if ( Services::WpGeneral()->isPermalinksEnabled() ) {
43
+ preg_match(
44
+ sprintf( '#^%s-(%s)-([a-z0-9]{7,9})$#i', $oFO->prefix(), implode( '|', $this->getPossibleWords() ) ),
45
+ trim( $oReq->getPath(), '/' ),
46
+ $aMatches
47
+ );
48
+ $bIsCheese = isset( $aMatches[ 2 ] );
49
+ }
50
+ else {
51
+ foreach ( $this->getPossibleWords() as $sWord ) {
52
+ if ( preg_match( '#^[a-z0-9]{7,9}$#i', $oReq->query( $oFO->prefix( $sWord ) ) ) ) {
53
+ $bIsCheese = true;
54
+ break;
55
+ }
56
+ }
57
+ }
58
+
59
+ return $bIsCheese;
60
+ }
61
+
62
+ public function insertMouseTrap() {
63
+ $sId = 'V'.rand();
64
+ echo sprintf(
65
+ '<style>#%s{display:none !important;}</style><a rel="nofollow" href="%s" title="%s" id="%s">%s</a>',
66
+ $sId, $this->buildTrapHref(), 'Click here to see something fantastic',
67
+ $sId, _wpsf__( 'Click to access the login or register cheese' )
68
+ );
69
+ }
70
+
71
+ /**
72
+ * @return string
73
+ */
74
+ private function buildTrapHref() {
75
+ /** @var \ICWP_WPSF_FeatureHandler_Mousetrap $oFO */
76
+ $oFO = $this->getMod();
77
+
78
+ $oWp = Services::WpGeneral();
79
+ $sKey = substr( md5( wp_generate_password() ), 5, rand( 7, 9 ) );
80
+ $sWord = $this->getPossibleWords()[ rand( 0, count( $this->getPossibleWords() ) ) ];
81
+ if ( $oWp->isPermalinksEnabled() ) {
82
+ $sLink = $oWp->getHomeUrl( sprintf( '/%s-%s/', $oFO->prefix( $sWord ), $sKey ) );
83
+ }
84
+ else {
85
+ $sLink = add_query_arg( [ $oFO->prefix( $sWord ) => $sKey ], $oWp->getHomeUrl() );
86
+ }
87
+ return $sLink;
88
+ }
89
+
90
+ /**
91
+ * @return bool
92
+ */
93
+ protected function isTransgression() {
94
+ /** @var \ICWP_WPSF_FeatureHandler_Mousetrap $oFO */
95
+ $oFO = $this->getMod();
96
+ return $oFO->isTransgressionLinkCheese();
97
+ }
98
+
99
+ /**
100
+ * @return $this
101
+ */
102
+ protected function writeAudit() {
103
+ $this->createNewAudit(
104
+ 'wpsf',
105
+ sprintf( _wpsf__( 'Link cheese access detected at "%s"' ), Services::Request()->getPath() ),
106
+ 2, 'mousetrap_linkcheese'
107
+ );
108
+ return $this;
109
+ }
110
+
111
+ /**
112
+ * @return string[]
113
+ */
114
+ private function getPossibleWords() {
115
+ return [
116
+ 'mouse',
117
+ 'cheese',
118
+ 'venus',
119
+ 'stilton',
120
+ 'cheddar',
121
+ ];
122
+ }
123
+ }
src/lib/src/Modules/UserManagement/Suspend/Base.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement\Suspend;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Modules\PluginControllerConsumer;
6
+ use FernleafSystems\Wordpress\Plugin\Shield\Users\ShieldUserMeta;
7
+
8
+ abstract class Base {
9
+
10
+ use PluginControllerConsumer;
11
+ const HOOK_PRIORITY = 1000; // so only authenticated user is notified of account state.
12
+
13
+ public function run() {
14
+ add_filter( 'authenticate', array( $this, 'checkUser' ), static::HOOK_PRIORITY, 1 );
15
+ }
16
+
17
+ /**
18
+ * Should be a filter added to WordPress's "authenticate" filter, but before WordPress performs
19
+ * it's own authentication (theirs is priority 30, so we could go in at around 20).
20
+ * @param null|\WP_User|\WP_Error $oUser
21
+ * @return \WP_User|\WP_Error
22
+ */
23
+ public function checkUser( $oUser ) {
24
+ if ( $oUser instanceof \WP_User ) {
25
+ $oUser = $this->processUser( $oUser, $this->getCon()->getUserMeta( $oUser ) );
26
+ }
27
+ return $oUser;
28
+ }
29
+
30
+ /**
31
+ * Test the User and its Meta and if it fails return \WP_Error; Always return Error or User
32
+ * @param \WP_User $oUser
33
+ * @param ShieldUserMeta $oMeta
34
+ * @return \WP_Error|\WP_User
35
+ */
36
+ abstract protected function processUser( $oUser, $oMeta );
37
+ }
src/lib/src/Modules/UserManagement/Suspend/Idle.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement\Suspend;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Users\ShieldUserMeta;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ class Idle extends Base {
9
+
10
+ /**
11
+ * @var int
12
+ */
13
+ private $nVerifiedExpired;
14
+
15
+ /**
16
+ * @param \WP_User $oUser
17
+ * @param ShieldUserMeta $oMeta
18
+ * @return \WP_Error|\WP_User
19
+ */
20
+ protected function processUser( $oUser, $oMeta ) {
21
+ if ( $this->isLastVerifiedAtExpired( $oMeta ) ) {
22
+ $oUser = new \WP_Error(
23
+ $this->getCon()->prefix( 'pass-expired' ),
24
+ 'Sorry, this account is suspended due to in-activity. Please reset your password to gain access to your account.'
25
+ );
26
+ }
27
+ return $oUser;
28
+ }
29
+
30
+ /**
31
+ * @param ShieldUserMeta $oMeta
32
+ * @return bool
33
+ */
34
+ protected function isLastVerifiedAtExpired( $oMeta ) {
35
+ return ( Services::Request()->ts() - $oMeta->getLastVerifiedAt() > $this->getVerifiedExpires() );
36
+ }
37
+
38
+ /**
39
+ * @return int
40
+ */
41
+ public function getVerifiedExpires() {
42
+ return (int)$this->nVerifiedExpired;
43
+ }
44
+
45
+ /**
46
+ * @param int $nVerifiedExpired
47
+ * @return $this
48
+ */
49
+ public function setVerifiedExpires( $nVerifiedExpired ) {
50
+ $this->nVerifiedExpired = $nVerifiedExpired;
51
+ return $this;
52
+ }
53
+ }
src/lib/src/Modules/UserManagement/Suspend/PasswordExpiry.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement\Suspend;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Users\ShieldUserMeta;
6
+ use FernleafSystems\Wordpress\Services\Services;
7
+
8
+ /**
9
+ * Class PasswordExpiry
10
+ * @package FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement\Suspend
11
+ */
12
+ class PasswordExpiry extends Base {
13
+
14
+ /**
15
+ * @var int
16
+ */
17
+ private $nMaxPasswordAge;
18
+
19
+ /**
20
+ * @param \WP_User $oUser
21
+ * @param ShieldUserMeta $oMeta
22
+ * @return \WP_Error|\WP_User
23
+ */
24
+ protected function processUser( $oUser, $oMeta ) {
25
+ if ( $this->isPassExpired( $oMeta ) ) {
26
+ $oUser = new \WP_Error(
27
+ $this->getCon()->prefix( 'pass-expired' ),
28
+ 'Sorry, this account is suspended due to expired password. Please reset your password to gain access to your account.'
29
+ );
30
+ }
31
+ return $oUser;
32
+ }
33
+
34
+ /**
35
+ * @param ShieldUserMeta $oMeta
36
+ * @return bool
37
+ */
38
+ private function isPassExpired( $oMeta ) {
39
+ $nPassStart = (int)$oMeta->pass_started_at;
40
+ if ( empty( $nPassStart ) ) {
41
+ $oMeta->pass_started_at = $oMeta->getLastVerifiedAt();
42
+ }
43
+ return ( Services::Request()->ts() - $oMeta->pass_started_at > $this->getMaxPasswordAge() );
44
+ }
45
+
46
+ /**
47
+ * @return int
48
+ */
49
+ public function getMaxPasswordAge() {
50
+ return (int)$this->nMaxPasswordAge;
51
+ }
52
+
53
+ /**
54
+ * @param int $nMaxPasswordAge
55
+ * @return $this
56
+ */
57
+ public function setMaxPasswordAge( $nMaxPasswordAge ) {
58
+ $this->nMaxPasswordAge = $nMaxPasswordAge;
59
+ return $this;
60
+ }
61
+ }
src/lib/src/Modules/UserManagement/Suspend/Suspended.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement\Suspend;
4
+
5
+ use FernleafSystems\Wordpress\Plugin\Shield\Users\ShieldUserMeta;
6
+
7
+ class Suspended extends Base {
8
+
9
+ const HOOK_PRIORITY = 999; // we process hard suspension before all others.
10
+
11
+ /**
12
+ * @param \WP_User $oUser
13
+ * @param ShieldUserMeta $oMeta
14
+ * @return \WP_Error|\WP_User
15
+ */
16
+ protected function processUser( $oUser, $oMeta ) {
17
+ if ( $oMeta->hard_suspended_at > 0 ) {
18
+ $oUser = new \WP_Error(
19
+ $this->getCon()->prefix( 'hard-suspended' ),
20
+ 'Sorry, this account is suspended. Please contact your website administrator to resolve this.'
21
+ );
22
+ }
23
+ return $oUser;
24
+ }
25
+ }
src/lib/src/Modules/UserManagement/UpdateUserPasswordMeta.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Plugin\Shield\Modules\UserManagement;
4
+
5
+ class UpdateUserPasswordMeta {
6
+
7
+ /**
8
+ * @param
9
+ */
10
+ public function run() {
11
+
12
+ $oQ = new \WP_User_Query();
13
+ }
14
+ }
src/lib/src/Scans/Helpers/WpCoreFileDownload.php CHANGED
@@ -44,7 +44,7 @@ class WpCoreFileDownload {
44
  */
45
  protected function getFileUrl( $sPath, $bUseLocale ) {
46
  $oWp = Services::WpGeneral();
47
- $sLocale = $oWp->getLocale( true );
48
  $bUseInternational = $bUseLocale && ( $sLocale != 'en_US' );
49
 
50
  if ( Services::WpGeneral()->isClassicPress() ) {
44
  */
45
  protected function getFileUrl( $sPath, $bUseLocale ) {
46
  $oWp = Services::WpGeneral();
47
+ $sLocale = $oWp->getLocaleForChecksums();
48
  $bUseInternational = $bUseLocale && ( $sLocale != 'en_US' );
49
 
50
  if ( Services::WpGeneral()->isClassicPress() ) {
src/lib/src/Scans/Wpv/Scanner.php CHANGED
@@ -87,29 +87,25 @@ class Scanner {
87
  * @return WpVulnVO[]
88
  */
89
  public function getPluginVulnerabilities( $sFile ) {
90
- $aVulns = array();
91
  $oWpPlugins = Services::WpPlugins();
92
 
93
  $sSlug = $oWpPlugins->getSlug( $sFile );
94
  if ( empty( $sSlug ) ) {
95
  $sSlug = dirname( $sFile );
96
  }
 
 
97
  try {
98
  $aVos = ( new RetrieveForItem() )->setContext( 'plugins' )
99
  ->setSlug( $sSlug )
100
  ->retrieve();
101
- $oPlugin = $oWpPlugins->getPluginAsVo( $sFile );
102
- $aVulns = array_filter(
103
- $aVos,
104
- function ( $oVo ) use ( $oPlugin ) {
105
- /** @var WpVulnVO $oVo */
106
- $sFixed = (string)$oVo->fixed_in;
107
- return ( empty ( $sFixed ) || version_compare( $oPlugin->Version, $sFixed, '<' ) );
108
- }
109
- );
110
  }
111
  catch ( \Exception $oE ) {
112
  }
 
113
  return $aVulns;
114
  }
115
 
@@ -118,26 +114,37 @@ class Scanner {
118
  * @return WpVulnVO[]
119
  */
120
  public function getThemeVulnerabilities( $sSlug ) {
121
- $aVulns = array();
122
- $oWpThemes = Services::WpThemes();
123
 
 
124
  try {
125
  $aVos = ( new RetrieveForItem() )->setContext( 'themes' )
126
  ->setSlug( $sSlug )
127
  ->retrieve();
128
- $oTheme = $oWpThemes->getTheme( $sSlug );
129
- $aVulns = array_filter(
130
- $aVos,
131
- function ( $oVo ) use ( $oTheme ) {
132
- /** @var WpVulnVO $oVo */
133
- $sFixed = $oVo->fixed_in;
134
- return ( empty ( $sFixed ) || version_compare( $oTheme->get( 'Version' ), $sFixed, '<' ) );
135
- }
136
- );
137
  }
138
  catch ( \Exception $oE ) {
139
  }
140
 
141
  return $aVulns;
142
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  }
87
  * @return WpVulnVO[]
88
  */
89
  public function getPluginVulnerabilities( $sFile ) {
 
90
  $oWpPlugins = Services::WpPlugins();
91
 
92
  $sSlug = $oWpPlugins->getSlug( $sFile );
93
  if ( empty( $sSlug ) ) {
94
  $sSlug = dirname( $sFile );
95
  }
96
+
97
+ $aVulns = [];
98
  try {
99
  $aVos = ( new RetrieveForItem() )->setContext( 'plugins' )
100
  ->setSlug( $sSlug )
101
  ->retrieve();
102
+ if ( !empty( $aVos ) ) {
103
+ $aVulns = $this->filterVulnerabilitiesAgainstVersion( $aVos, $oWpPlugins->getPluginAsVo( $sFile )->Version );
104
+ }
 
 
 
 
 
 
105
  }
106
  catch ( \Exception $oE ) {
107
  }
108
+
109
  return $aVulns;
110
  }
111
 
114
  * @return WpVulnVO[]
115
  */
116
  public function getThemeVulnerabilities( $sSlug ) {
 
 
117
 
118
+ $aVulns = [];
119
  try {
120
  $aVos = ( new RetrieveForItem() )->setContext( 'themes' )
121
  ->setSlug( $sSlug )
122
  ->retrieve();
123
+ if ( !empty( $aVos ) ) {
124
+ $oTheme = Services::WpThemes()->getTheme( $sSlug );
125
+ $aVulns = $this->filterVulnerabilitiesAgainstVersion( $aVos, $oTheme->get( 'Version' ) );
126
+ }
 
 
 
 
 
127
  }
128
  catch ( \Exception $oE ) {
129
  }
130
 
131
  return $aVulns;
132
  }
133
+
134
+ /**
135
+ * @param WpVulnVO[] $aVos
136
+ * @param string $sCurrentVersion
137
+ * @return WpVulnVO[]
138
+ */
139
+ private function filterVulnerabilitiesAgainstVersion( $aVos, $sCurrentVersion ) {
140
+ $sCurrentVersion = trim( $sCurrentVersion, 'v' );
141
+ return array_filter(
142
+ $aVos,
143
+ function ( $oVo ) use ( $sCurrentVersion ) {
144
+ /** @var WpVulnVO $oVo */
145
+ $sFixed = $oVo->fixed_in;
146
+ return ( empty ( $sFixed ) || version_compare( $sCurrentVersion, $sFixed, '<' ) );
147
+ }
148
+ );
149
+ }
150
  }
src/lib/src/Users/ShieldUserMeta.php CHANGED
@@ -2,6 +2,8 @@
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Users;
4
 
 
 
5
  /**
6
  * Class UserMeta
7
  * @package FernleafSystems\Wordpress\Plugin\Shield\Users
@@ -20,7 +22,31 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\Users;
20
  * @property bool $yubi_validated
21
  * @property int $last_login_at
22
  * @property bool $wc_social_login_valid
 
23
  */
24
  class ShieldUserMeta extends \FernleafSystems\Wordpress\Services\Utilities\PluginUserMeta {
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  }
2
 
3
  namespace FernleafSystems\Wordpress\Plugin\Shield\Users;
4
 
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
  /**
8
  * Class UserMeta
9
  * @package FernleafSystems\Wordpress\Plugin\Shield\Users
22
  * @property bool $yubi_validated
23
  * @property int $last_login_at
24
  * @property bool $wc_social_login_valid
25
+ * @property bool $hard_suspended_at
26
  */
27
  class ShieldUserMeta extends \FernleafSystems\Wordpress\Services\Utilities\PluginUserMeta {
28
 
29
+ /**
30
+ * @return int
31
+ */
32
+ public function getLastVerifiedAt() {
33
+ $nLastVerified = (int)max( $this->last_login_at, $this->pass_started_at );
34
+ if ( $nLastVerified < 1 ) {
35
+ $nLastVerified = Services::Request()->ts();
36
+ }
37
+ return $nLastVerified;
38
+ }
39
+
40
+ /**
41
+ * @param string $sHashedPassword
42
+ * @return $this
43
+ */
44
+ public function setPasswordStartedAt( $sHashedPassword ) {
45
+ $sNewHash = substr( sha1( $sHashedPassword ), 6, 4 );
46
+ if ( !isset( $this->pass_hash ) || ( $this->pass_hash != $sNewHash ) ) {
47
+ $this->pass_hash = $sNewHash;
48
+ $this->pass_started_at = Services::Request()->ts();
49
+ }
50
+ return $this;
51
+ }
52
  }
src/lib/vendor/composer/autoload_classmap.php CHANGED
@@ -16,6 +16,31 @@ return array(
16
  'FernleafSystems\\Utilities\\Data\\Adapter\\StdClassAdapter' => $vendorDir . '/fernleafsystems/utilities/src/Data/Adapter/StdClassAdapter.php',
17
  'FernleafSystems\\Utilities\\Response' => $vendorDir . '/fernleafsystems/utilities/src/Response.php',
18
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\AuditTrail\\Auditor' => $baseDir . '/src/AuditTrail/Auditor.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Crons\\StandardCron' => $baseDir . '/src/Crons/StandardCron.php',
20
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Delete' => $baseDir . '/src/Databases/AdminNotes/Delete.php',
21
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\EntryVO' => $baseDir . '/src/Databases/AdminNotes/EntryVO.php',
@@ -36,6 +61,12 @@ return array(
36
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Insert' => $baseDir . '/src/Databases/Base/Insert.php',
37
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Select' => $baseDir . '/src/Databases/Base/Select.php',
38
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Update' => $baseDir . '/src/Databases/Base/Update.php',
 
 
 
 
 
 
39
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Comments\\Delete' => $baseDir . '/src/Databases/Comments/Delete.php',
40
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Comments\\EntryVO' => $baseDir . '/src/Databases/Comments/EntryVO.php',
41
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Comments\\Handler' => $baseDir . '/src/Databases/Comments/Handler.php',
@@ -74,8 +105,19 @@ return array(
74
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Select' => $baseDir . '/src/Databases/Traffic/Select.php',
75
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\License\\EddLicenseVO' => $baseDir . '/src/License/EddLicenseVO.php',
76
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\ModConsumer' => $baseDir . '/src/Modules/ModConsumer.php',
 
 
 
 
 
 
77
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\OptsConsumer' => $baseDir . '/src/Modules/OptsConsumer.php',
78
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\PluginControllerConsumer' => $baseDir . '/src/Modules/PluginControllerConsumer.php',
 
 
 
 
 
79
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ConvertResultsToVos' => $baseDir . '/src/Scans/Apc/ConvertResultsToVos.php',
80
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ConvertVosToResults' => $baseDir . '/src/Scans/Apc/ConvertVosToResults.php',
81
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ResultItem' => $baseDir . '/src/Scans/Apc/ResultItem.php',
@@ -188,9 +230,15 @@ return array(
188
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Data' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Data.php',
189
  'FernleafSystems\\Wordpress\\Services\\Utilities\\DataManipulation' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/DataManipulation.php',
190
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Email' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Email.php',
 
 
 
 
 
191
  'FernleafSystems\\Wordpress\\Services\\Utilities\\GeoIp' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/GeoIp.php',
192
  'FernleafSystems\\Wordpress\\Services\\Utilities\\HttpRequest' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/HttpRequest.php',
193
  'FernleafSystems\\Wordpress\\Services\\Utilities\\IpUtils' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/IpUtils.php',
 
194
  'FernleafSystems\\Wordpress\\Services\\Utilities\\PluginUserMeta' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/PluginUserMeta.php',
195
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Render' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Render.php',
196
  'FernleafSystems\\Wordpress\\Services\\Utilities\\ServiceProviders' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/ServiceProviders.php',
@@ -254,6 +302,7 @@ return array(
254
  'ICWP_WPSF_FeatureHandler_License' => $baseDir . '/../features/license.php',
255
  'ICWP_WPSF_FeatureHandler_Lockdown' => $baseDir . '/../features/lockdown.php',
256
  'ICWP_WPSF_FeatureHandler_LoginProtect' => $baseDir . '/../features/login_protect.php',
 
257
  'ICWP_WPSF_FeatureHandler_Plugin' => $baseDir . '/../features/plugin.php',
258
  'ICWP_WPSF_FeatureHandler_Sessions' => $baseDir . '/../features/sessions.php',
259
  'ICWP_WPSF_FeatureHandler_Statistics' => $baseDir . '/../features/statistics.php',
@@ -269,6 +318,7 @@ return array(
269
  'ICWP_WPSF_Processor_AdminAccess_Whitelabel' => $baseDir . '/../processors/adminaccess_whitelabel.php',
270
  'ICWP_WPSF_Processor_AuditTrail' => $baseDir . '/../processors/audit_trail.php',
271
  'ICWP_WPSF_Processor_AuditTrail_Auditor' => $baseDir . '/../processors/audit_trail_auditor.php',
 
272
  'ICWP_WPSF_Processor_AuditTrail_Emails' => $baseDir . '/../processors/audit_trail_emails.php',
273
  'ICWP_WPSF_Processor_AuditTrail_Plugins' => $baseDir . '/../processors/audit_trail_plugins.php',
274
  'ICWP_WPSF_Processor_AuditTrail_Posts' => $baseDir . '/../processors/audit_trail_posts.php',
@@ -314,10 +364,12 @@ return array(
314
  'ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth' => $baseDir . '/../processors/loginprotect_intentprovider_email.php',
315
  'ICWP_WPSF_Processor_LoginProtect_WpLogin' => $baseDir . '/../processors/loginprotect_wplogin.php',
316
  'ICWP_WPSF_Processor_LoginProtect_Yubikey' => $baseDir . '/../processors/loginprotect_intentprovider_yubikey.php',
 
317
  'ICWP_WPSF_Processor_Plugin' => $baseDir . '/../processors/plugin.php',
318
  'ICWP_WPSF_Processor_Plugin_Badge' => $baseDir . '/../processors/plugin_badge.php',
319
  'ICWP_WPSF_Processor_Plugin_BadgeWidget' => $baseDir . '/../processors/plugin_badgewidget.php',
320
  'ICWP_WPSF_Processor_Plugin_CronDaily' => $baseDir . '/../processors/plugin_crondaily.php',
 
321
  'ICWP_WPSF_Processor_Plugin_ImportExport' => $baseDir . '/../processors/plugin_importexport.php',
322
  'ICWP_WPSF_Processor_Plugin_Notes' => $baseDir . '/../processors/plugin_notes.php',
323
  'ICWP_WPSF_Processor_Plugin_Tracking' => $baseDir . '/../processors/plugin_tracking.php',
@@ -331,6 +383,7 @@ return array(
331
  'ICWP_WPSF_Processor_UserManagement' => $baseDir . '/../processors/user_management.php',
332
  'ICWP_WPSF_Processor_UserManagement_Passwords' => $baseDir . '/../processors/usermanagement_passwords.php',
333
  'ICWP_WPSF_Processor_UserManagement_Sessions' => $baseDir . '/../processors/usermanagement_sessions.php',
 
334
  'ICWP_WPSF_Query_Statistics_Base' => $baseDir . '/../query/base/statistics_base.php',
335
  'ICWP_WPSF_Query_Statistics_Consolidation' => $baseDir . '/../query/statistics/consolidation.php',
336
  'ICWP_WPSF_Query_Statistics_Reporting' => $baseDir . '/../query/statistics/reporting.php',
@@ -514,6 +567,7 @@ return array(
514
  'Twig\\Node\\BlockReferenceNode' => $vendorDir . '/twig/twig/src/Node/BlockReferenceNode.php',
515
  'Twig\\Node\\BodyNode' => $vendorDir . '/twig/twig/src/Node/BodyNode.php',
516
  'Twig\\Node\\CheckSecurityNode' => $vendorDir . '/twig/twig/src/Node/CheckSecurityNode.php',
 
517
  'Twig\\Node\\DeprecatedNode' => $vendorDir . '/twig/twig/src/Node/DeprecatedNode.php',
518
  'Twig\\Node\\DoNode' => $vendorDir . '/twig/twig/src/Node/DoNode.php',
519
  'Twig\\Node\\EmbedNode' => $vendorDir . '/twig/twig/src/Node/EmbedNode.php',
16
  'FernleafSystems\\Utilities\\Data\\Adapter\\StdClassAdapter' => $vendorDir . '/fernleafsystems/utilities/src/Data/Adapter/StdClassAdapter.php',
17
  'FernleafSystems\\Utilities\\Response' => $vendorDir . '/fernleafsystems/utilities/src/Response.php',
18
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\AuditTrail\\Auditor' => $baseDir . '/src/AuditTrail/Auditor.php',
19
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\Base' => $baseDir . '/src/ChangeTrack/Diff/Base.php',
20
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\DiffComments' => $baseDir . '/src/ChangeTrack/Diff/DiffComments.php',
21
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\DiffMedia' => $baseDir . '/src/ChangeTrack/Diff/DiffMedia.php',
22
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\DiffPages' => $baseDir . '/src/ChangeTrack/Diff/DiffPages.php',
23
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\DiffPlugins' => $baseDir . '/src/ChangeTrack/Diff/DiffPlugins.php',
24
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\DiffPosts' => $baseDir . '/src/ChangeTrack/Diff/DiffPosts.php',
25
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\DiffThemes' => $baseDir . '/src/ChangeTrack/Diff/DiffThemes.php',
26
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\DiffUsers' => $baseDir . '/src/ChangeTrack/Diff/DiffUsers.php',
27
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Base' => $baseDir . '/src/ChangeTrack/Report/Build/Base.php',
28
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Comments' => $baseDir . '/src/ChangeTrack/Report/Build/Comments.php',
29
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Media' => $baseDir . '/src/ChangeTrack/Report/Build/Media.php',
30
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Pages' => $baseDir . '/src/ChangeTrack/Report/Build/Pages.php',
31
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Plugins' => $baseDir . '/src/ChangeTrack/Report/Build/Plugins.php',
32
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Posts' => $baseDir . '/src/ChangeTrack/Report/Build/Posts.php',
33
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Themes' => $baseDir . '/src/ChangeTrack/Report/Build/Themes.php',
34
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Users' => $baseDir . '/src/ChangeTrack/Report/Build/Users.php',
35
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\BuildComments' => $baseDir . '/src/ChangeTrack/Snapshot/BuildComments.php',
36
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\BuildMedia' => $baseDir . '/src/ChangeTrack/Snapshot/BuildMedia.php',
37
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\BuildPages' => $baseDir . '/src/ChangeTrack/Snapshot/BuildPages.php',
38
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\BuildPlugins' => $baseDir . '/src/ChangeTrack/Snapshot/BuildPlugins.php',
39
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\BuildPosts' => $baseDir . '/src/ChangeTrack/Snapshot/BuildPosts.php',
40
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\BuildThemes' => $baseDir . '/src/ChangeTrack/Snapshot/BuildThemes.php',
41
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\BuildUsers' => $baseDir . '/src/ChangeTrack/Snapshot/BuildUsers.php',
42
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\Collate' => $baseDir . '/src/ChangeTrack/Snapshot/Collate.php',
43
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\SnapshotsConsumer' => $baseDir . '/src/ChangeTrack/Snapshot/SnapshotsConsumer.php',
44
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Crons\\StandardCron' => $baseDir . '/src/Crons/StandardCron.php',
45
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Delete' => $baseDir . '/src/Databases/AdminNotes/Delete.php',
46
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\EntryVO' => $baseDir . '/src/Databases/AdminNotes/EntryVO.php',
61
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Insert' => $baseDir . '/src/Databases/Base/Insert.php',
62
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Select' => $baseDir . '/src/Databases/Base/Select.php',
63
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Update' => $baseDir . '/src/Databases/Base/Update.php',
64
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Delete' => $baseDir . '/src/Databases/ChangeTracking/Delete.php',
65
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\EntryVO' => $baseDir . '/src/Databases/ChangeTracking/EntryVO.php',
66
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Handler' => $baseDir . '/src/Databases/ChangeTracking/Handler.php',
67
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Insert' => $baseDir . '/src/Databases/ChangeTracking/Insert.php',
68
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Select' => $baseDir . '/src/Databases/ChangeTracking/Select.php',
69
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Update' => $baseDir . '/src/Databases/ChangeTracking/Update.php',
70
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Comments\\Delete' => $baseDir . '/src/Databases/Comments/Delete.php',
71
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Comments\\EntryVO' => $baseDir . '/src/Databases/Comments/EntryVO.php',
72
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Comments\\Handler' => $baseDir . '/src/Databases/Comments/Handler.php',
105
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Select' => $baseDir . '/src/Databases/Traffic/Select.php',
106
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\License\\EddLicenseVO' => $baseDir . '/src/License/EddLicenseVO.php',
107
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\ModConsumer' => $baseDir . '/src/Modules/ModConsumer.php',
108
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\MouseTrap\\Base' => $baseDir . '/src/Modules/MouseTrap/Base.php',
109
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\MouseTrap\\Detect404' => $baseDir . '/src/Modules/MouseTrap/Detect404.php',
110
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\MouseTrap\\DetectXmlRpc' => $baseDir . '/src/Modules/MouseTrap/DetectXmlRpc.php',
111
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\MouseTrap\\FakeWebCrawler' => $baseDir . '/src/Modules/MouseTrap/FakeWebCrawler.php',
112
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\MouseTrap\\InvalidUsername' => $baseDir . '/src/Modules/MouseTrap/InvalidUsername.php',
113
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\MouseTrap\\LinkCheese' => $baseDir . '/src/Modules/MouseTrap/LinkCheese.php',
114
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\OptsConsumer' => $baseDir . '/src/Modules/OptsConsumer.php',
115
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\PluginControllerConsumer' => $baseDir . '/src/Modules/PluginControllerConsumer.php',
116
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\Suspend\\Base' => $baseDir . '/src/Modules/UserManagement/Suspend/Base.php',
117
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\Suspend\\Idle' => $baseDir . '/src/Modules/UserManagement/Suspend/Idle.php',
118
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\Suspend\\PasswordExpiry' => $baseDir . '/src/Modules/UserManagement/Suspend/PasswordExpiry.php',
119
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\Suspend\\Suspended' => $baseDir . '/src/Modules/UserManagement/Suspend/Suspended.php',
120
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\UpdateUserPasswordMeta' => $baseDir . '/src/Modules/UserManagement/UpdateUserPasswordMeta.php',
121
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ConvertResultsToVos' => $baseDir . '/src/Scans/Apc/ConvertResultsToVos.php',
122
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ConvertVosToResults' => $baseDir . '/src/Scans/Apc/ConvertVosToResults.php',
123
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ResultItem' => $baseDir . '/src/Scans/Apc/ResultItem.php',
230
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Data' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Data.php',
231
  'FernleafSystems\\Wordpress\\Services\\Utilities\\DataManipulation' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/DataManipulation.php',
232
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Email' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Email.php',
233
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\Encrypt\\OpenSslEncrypt' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncrypt.php',
234
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\Encrypt\\OpenSslEncryptVo' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncryptVo.php',
235
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\ReadDataFromFileEncrypted' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/File/ReadDataFromFileEncrypted.php',
236
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\TestFileWritable' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/File/TestFileWritable.php',
237
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\WriteDataToFileEncrypted' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/File/WriteDataToFileEncrypted.php',
238
  'FernleafSystems\\Wordpress\\Services\\Utilities\\GeoIp' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/GeoIp.php',
239
  'FernleafSystems\\Wordpress\\Services\\Utilities\\HttpRequest' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/HttpRequest.php',
240
  'FernleafSystems\\Wordpress\\Services\\Utilities\\IpUtils' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/IpUtils.php',
241
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\VisitorIpDetection' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Net/VisitorIpDetection.php',
242
  'FernleafSystems\\Wordpress\\Services\\Utilities\\PluginUserMeta' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/PluginUserMeta.php',
243
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Render' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/Render.php',
244
  'FernleafSystems\\Wordpress\\Services\\Utilities\\ServiceProviders' => $vendorDir . '/fernleafsystems/wordpress-services/src/Utilities/ServiceProviders.php',
302
  'ICWP_WPSF_FeatureHandler_License' => $baseDir . '/../features/license.php',
303
  'ICWP_WPSF_FeatureHandler_Lockdown' => $baseDir . '/../features/lockdown.php',
304
  'ICWP_WPSF_FeatureHandler_LoginProtect' => $baseDir . '/../features/login_protect.php',
305
+ 'ICWP_WPSF_FeatureHandler_Mousetrap' => $baseDir . '/../features/mousetrap.php',
306
  'ICWP_WPSF_FeatureHandler_Plugin' => $baseDir . '/../features/plugin.php',
307
  'ICWP_WPSF_FeatureHandler_Sessions' => $baseDir . '/../features/sessions.php',
308
  'ICWP_WPSF_FeatureHandler_Statistics' => $baseDir . '/../features/statistics.php',
318
  'ICWP_WPSF_Processor_AdminAccess_Whitelabel' => $baseDir . '/../processors/adminaccess_whitelabel.php',
319
  'ICWP_WPSF_Processor_AuditTrail' => $baseDir . '/../processors/audit_trail.php',
320
  'ICWP_WPSF_Processor_AuditTrail_Auditor' => $baseDir . '/../processors/audit_trail_auditor.php',
321
+ 'ICWP_WPSF_Processor_AuditTrail_ChangeTracking' => $baseDir . '/../processors/audit_trail_changetracking.php',
322
  'ICWP_WPSF_Processor_AuditTrail_Emails' => $baseDir . '/../processors/audit_trail_emails.php',
323
  'ICWP_WPSF_Processor_AuditTrail_Plugins' => $baseDir . '/../processors/audit_trail_plugins.php',
324
  'ICWP_WPSF_Processor_AuditTrail_Posts' => $baseDir . '/../processors/audit_trail_posts.php',
364
  'ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth' => $baseDir . '/../processors/loginprotect_intentprovider_email.php',
365
  'ICWP_WPSF_Processor_LoginProtect_WpLogin' => $baseDir . '/../processors/loginprotect_wplogin.php',
366
  'ICWP_WPSF_Processor_LoginProtect_Yubikey' => $baseDir . '/../processors/loginprotect_intentprovider_yubikey.php',
367
+ 'ICWP_WPSF_Processor_Mousetrap' => $baseDir . '/../processors/mousetrap.php',
368
  'ICWP_WPSF_Processor_Plugin' => $baseDir . '/../processors/plugin.php',
369
  'ICWP_WPSF_Processor_Plugin_Badge' => $baseDir . '/../processors/plugin_badge.php',
370
  'ICWP_WPSF_Processor_Plugin_BadgeWidget' => $baseDir . '/../processors/plugin_badgewidget.php',
371
  'ICWP_WPSF_Processor_Plugin_CronDaily' => $baseDir . '/../processors/plugin_crondaily.php',
372
+ 'ICWP_WPSF_Processor_Plugin_CronHourly' => $baseDir . '/../processors/plugin_cronhourly.php',
373
  'ICWP_WPSF_Processor_Plugin_ImportExport' => $baseDir . '/../processors/plugin_importexport.php',
374
  'ICWP_WPSF_Processor_Plugin_Notes' => $baseDir . '/../processors/plugin_notes.php',
375
  'ICWP_WPSF_Processor_Plugin_Tracking' => $baseDir . '/../processors/plugin_tracking.php',
383
  'ICWP_WPSF_Processor_UserManagement' => $baseDir . '/../processors/user_management.php',
384
  'ICWP_WPSF_Processor_UserManagement_Passwords' => $baseDir . '/../processors/usermanagement_passwords.php',
385
  'ICWP_WPSF_Processor_UserManagement_Sessions' => $baseDir . '/../processors/usermanagement_sessions.php',
386
+ 'ICWP_WPSF_Processor_UserManagement_Suspend' => $baseDir . '/../processors/usermanagement_suspend.php',
387
  'ICWP_WPSF_Query_Statistics_Base' => $baseDir . '/../query/base/statistics_base.php',
388
  'ICWP_WPSF_Query_Statistics_Consolidation' => $baseDir . '/../query/statistics/consolidation.php',
389
  'ICWP_WPSF_Query_Statistics_Reporting' => $baseDir . '/../query/statistics/reporting.php',
567
  'Twig\\Node\\BlockReferenceNode' => $vendorDir . '/twig/twig/src/Node/BlockReferenceNode.php',
568
  'Twig\\Node\\BodyNode' => $vendorDir . '/twig/twig/src/Node/BodyNode.php',
569
  'Twig\\Node\\CheckSecurityNode' => $vendorDir . '/twig/twig/src/Node/CheckSecurityNode.php',
570
+ 'Twig\\Node\\CheckToStringNode' => $vendorDir . '/twig/twig/src/Node/CheckToStringNode.php',
571
  'Twig\\Node\\DeprecatedNode' => $vendorDir . '/twig/twig/src/Node/DeprecatedNode.php',
572
  'Twig\\Node\\DoNode' => $vendorDir . '/twig/twig/src/Node/DoNode.php',
573
  'Twig\\Node\\EmbedNode' => $vendorDir . '/twig/twig/src/Node/EmbedNode.php',
src/lib/vendor/composer/autoload_static.php CHANGED
@@ -164,6 +164,31 @@ class ComposerStaticInit18a31866e67f0a0bfffdc031786ecae1
164
  'FernleafSystems\\Utilities\\Data\\Adapter\\StdClassAdapter' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Data/Adapter/StdClassAdapter.php',
165
  'FernleafSystems\\Utilities\\Response' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Response.php',
166
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\AuditTrail\\Auditor' => __DIR__ . '/../..' . '/src/AuditTrail/Auditor.php',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Crons\\StandardCron' => __DIR__ . '/../..' . '/src/Crons/StandardCron.php',
168
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Delete' => __DIR__ . '/../..' . '/src/Databases/AdminNotes/Delete.php',
169
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\EntryVO' => __DIR__ . '/../..' . '/src/Databases/AdminNotes/EntryVO.php',
@@ -184,6 +209,12 @@ class ComposerStaticInit18a31866e67f0a0bfffdc031786ecae1
184
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Insert' => __DIR__ . '/../..' . '/src/Databases/Base/Insert.php',
185
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Select' => __DIR__ . '/../..' . '/src/Databases/Base/Select.php',
186
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Update' => __DIR__ . '/../..' . '/src/Databases/Base/Update.php',
 
 
 
 
 
 
187
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Comments\\Delete' => __DIR__ . '/../..' . '/src/Databases/Comments/Delete.php',
188
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Comments\\EntryVO' => __DIR__ . '/../..' . '/src/Databases/Comments/EntryVO.php',
189
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Comments\\Handler' => __DIR__ . '/../..' . '/src/Databases/Comments/Handler.php',
@@ -222,8 +253,19 @@ class ComposerStaticInit18a31866e67f0a0bfffdc031786ecae1
222
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Select' => __DIR__ . '/../..' . '/src/Databases/Traffic/Select.php',
223
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\License\\EddLicenseVO' => __DIR__ . '/../..' . '/src/License/EddLicenseVO.php',
224
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\ModConsumer' => __DIR__ . '/../..' . '/src/Modules/ModConsumer.php',
 
 
 
 
 
 
225
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\OptsConsumer' => __DIR__ . '/../..' . '/src/Modules/OptsConsumer.php',
226
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\PluginControllerConsumer' => __DIR__ . '/../..' . '/src/Modules/PluginControllerConsumer.php',
 
 
 
 
 
227
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ConvertResultsToVos' => __DIR__ . '/../..' . '/src/Scans/Apc/ConvertResultsToVos.php',
228
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ConvertVosToResults' => __DIR__ . '/../..' . '/src/Scans/Apc/ConvertVosToResults.php',
229
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ResultItem' => __DIR__ . '/../..' . '/src/Scans/Apc/ResultItem.php',
@@ -336,9 +378,15 @@ class ComposerStaticInit18a31866e67f0a0bfffdc031786ecae1
336
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Data' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Data.php',
337
  'FernleafSystems\\Wordpress\\Services\\Utilities\\DataManipulation' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/DataManipulation.php',
338
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Email' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Email.php',
 
 
 
 
 
339
  'FernleafSystems\\Wordpress\\Services\\Utilities\\GeoIp' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/GeoIp.php',
340
  'FernleafSystems\\Wordpress\\Services\\Utilities\\HttpRequest' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/HttpRequest.php',
341
  'FernleafSystems\\Wordpress\\Services\\Utilities\\IpUtils' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/IpUtils.php',
 
342
  'FernleafSystems\\Wordpress\\Services\\Utilities\\PluginUserMeta' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/PluginUserMeta.php',
343
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Render' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Render.php',
344
  'FernleafSystems\\Wordpress\\Services\\Utilities\\ServiceProviders' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/ServiceProviders.php',
@@ -402,6 +450,7 @@ class ComposerStaticInit18a31866e67f0a0bfffdc031786ecae1
402
  'ICWP_WPSF_FeatureHandler_License' => __DIR__ . '/../..' . '/../features/license.php',
403
  'ICWP_WPSF_FeatureHandler_Lockdown' => __DIR__ . '/../..' . '/../features/lockdown.php',
404
  'ICWP_WPSF_FeatureHandler_LoginProtect' => __DIR__ . '/../..' . '/../features/login_protect.php',
 
405
  'ICWP_WPSF_FeatureHandler_Plugin' => __DIR__ . '/../..' . '/../features/plugin.php',
406
  'ICWP_WPSF_FeatureHandler_Sessions' => __DIR__ . '/../..' . '/../features/sessions.php',
407
  'ICWP_WPSF_FeatureHandler_Statistics' => __DIR__ . '/../..' . '/../features/statistics.php',
@@ -417,6 +466,7 @@ class ComposerStaticInit18a31866e67f0a0bfffdc031786ecae1
417
  'ICWP_WPSF_Processor_AdminAccess_Whitelabel' => __DIR__ . '/../..' . '/../processors/adminaccess_whitelabel.php',
418
  'ICWP_WPSF_Processor_AuditTrail' => __DIR__ . '/../..' . '/../processors/audit_trail.php',
419
  'ICWP_WPSF_Processor_AuditTrail_Auditor' => __DIR__ . '/../..' . '/../processors/audit_trail_auditor.php',
 
420
  'ICWP_WPSF_Processor_AuditTrail_Emails' => __DIR__ . '/../..' . '/../processors/audit_trail_emails.php',
421
  'ICWP_WPSF_Processor_AuditTrail_Plugins' => __DIR__ . '/../..' . '/../processors/audit_trail_plugins.php',
422
  'ICWP_WPSF_Processor_AuditTrail_Posts' => __DIR__ . '/../..' . '/../processors/audit_trail_posts.php',
@@ -462,10 +512,12 @@ class ComposerStaticInit18a31866e67f0a0bfffdc031786ecae1
462
  'ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth' => __DIR__ . '/../..' . '/../processors/loginprotect_intentprovider_email.php',
463
  'ICWP_WPSF_Processor_LoginProtect_WpLogin' => __DIR__ . '/../..' . '/../processors/loginprotect_wplogin.php',
464
  'ICWP_WPSF_Processor_LoginProtect_Yubikey' => __DIR__ . '/../..' . '/../processors/loginprotect_intentprovider_yubikey.php',
 
465
  'ICWP_WPSF_Processor_Plugin' => __DIR__ . '/../..' . '/../processors/plugin.php',
466
  'ICWP_WPSF_Processor_Plugin_Badge' => __DIR__ . '/../..' . '/../processors/plugin_badge.php',
467
  'ICWP_WPSF_Processor_Plugin_BadgeWidget' => __DIR__ . '/../..' . '/../processors/plugin_badgewidget.php',
468
  'ICWP_WPSF_Processor_Plugin_CronDaily' => __DIR__ . '/../..' . '/../processors/plugin_crondaily.php',
 
469
  'ICWP_WPSF_Processor_Plugin_ImportExport' => __DIR__ . '/../..' . '/../processors/plugin_importexport.php',
470
  'ICWP_WPSF_Processor_Plugin_Notes' => __DIR__ . '/../..' . '/../processors/plugin_notes.php',
471
  'ICWP_WPSF_Processor_Plugin_Tracking' => __DIR__ . '/../..' . '/../processors/plugin_tracking.php',
@@ -479,6 +531,7 @@ class ComposerStaticInit18a31866e67f0a0bfffdc031786ecae1
479
  'ICWP_WPSF_Processor_UserManagement' => __DIR__ . '/../..' . '/../processors/user_management.php',
480
  'ICWP_WPSF_Processor_UserManagement_Passwords' => __DIR__ . '/../..' . '/../processors/usermanagement_passwords.php',
481
  'ICWP_WPSF_Processor_UserManagement_Sessions' => __DIR__ . '/../..' . '/../processors/usermanagement_sessions.php',
 
482
  'ICWP_WPSF_Query_Statistics_Base' => __DIR__ . '/../..' . '/../query/base/statistics_base.php',
483
  'ICWP_WPSF_Query_Statistics_Consolidation' => __DIR__ . '/../..' . '/../query/statistics/consolidation.php',
484
  'ICWP_WPSF_Query_Statistics_Reporting' => __DIR__ . '/../..' . '/../query/statistics/reporting.php',
@@ -662,6 +715,7 @@ class ComposerStaticInit18a31866e67f0a0bfffdc031786ecae1
662
  'Twig\\Node\\BlockReferenceNode' => __DIR__ . '/..' . '/twig/twig/src/Node/BlockReferenceNode.php',
663
  'Twig\\Node\\BodyNode' => __DIR__ . '/..' . '/twig/twig/src/Node/BodyNode.php',
664
  'Twig\\Node\\CheckSecurityNode' => __DIR__ . '/..' . '/twig/twig/src/Node/CheckSecurityNode.php',
 
665
  'Twig\\Node\\DeprecatedNode' => __DIR__ . '/..' . '/twig/twig/src/Node/DeprecatedNode.php',
666
  'Twig\\Node\\DoNode' => __DIR__ . '/..' . '/twig/twig/src/Node/DoNode.php',
667
  'Twig\\Node\\EmbedNode' => __DIR__ . '/..' . '/twig/twig/src/Node/EmbedNode.php',
164
  'FernleafSystems\\Utilities\\Data\\Adapter\\StdClassAdapter' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Data/Adapter/StdClassAdapter.php',
165
  'FernleafSystems\\Utilities\\Response' => __DIR__ . '/..' . '/fernleafsystems/utilities/src/Response.php',
166
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\AuditTrail\\Auditor' => __DIR__ . '/../..' . '/src/AuditTrail/Auditor.php',
167
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\Base' => __DIR__ . '/../..' . '/src/ChangeTrack/Diff/Base.php',
168
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\DiffComments' => __DIR__ . '/../..' . '/src/ChangeTrack/Diff/DiffComments.php',
169
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\DiffMedia' => __DIR__ . '/../..' . '/src/ChangeTrack/Diff/DiffMedia.php',
170
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\DiffPages' => __DIR__ . '/../..' . '/src/ChangeTrack/Diff/DiffPages.php',
171
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\DiffPlugins' => __DIR__ . '/../..' . '/src/ChangeTrack/Diff/DiffPlugins.php',
172
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\DiffPosts' => __DIR__ . '/../..' . '/src/ChangeTrack/Diff/DiffPosts.php',
173
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\DiffThemes' => __DIR__ . '/../..' . '/src/ChangeTrack/Diff/DiffThemes.php',
174
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Diff\\DiffUsers' => __DIR__ . '/../..' . '/src/ChangeTrack/Diff/DiffUsers.php',
175
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Base' => __DIR__ . '/../..' . '/src/ChangeTrack/Report/Build/Base.php',
176
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Comments' => __DIR__ . '/../..' . '/src/ChangeTrack/Report/Build/Comments.php',
177
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Media' => __DIR__ . '/../..' . '/src/ChangeTrack/Report/Build/Media.php',
178
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Pages' => __DIR__ . '/../..' . '/src/ChangeTrack/Report/Build/Pages.php',
179
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Plugins' => __DIR__ . '/../..' . '/src/ChangeTrack/Report/Build/Plugins.php',
180
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Posts' => __DIR__ . '/../..' . '/src/ChangeTrack/Report/Build/Posts.php',
181
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Themes' => __DIR__ . '/../..' . '/src/ChangeTrack/Report/Build/Themes.php',
182
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Report\\Build\\Users' => __DIR__ . '/../..' . '/src/ChangeTrack/Report/Build/Users.php',
183
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\BuildComments' => __DIR__ . '/../..' . '/src/ChangeTrack/Snapshot/BuildComments.php',
184
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\BuildMedia' => __DIR__ . '/../..' . '/src/ChangeTrack/Snapshot/BuildMedia.php',
185
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\BuildPages' => __DIR__ . '/../..' . '/src/ChangeTrack/Snapshot/BuildPages.php',
186
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\BuildPlugins' => __DIR__ . '/../..' . '/src/ChangeTrack/Snapshot/BuildPlugins.php',
187
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\BuildPosts' => __DIR__ . '/../..' . '/src/ChangeTrack/Snapshot/BuildPosts.php',
188
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\BuildThemes' => __DIR__ . '/../..' . '/src/ChangeTrack/Snapshot/BuildThemes.php',
189
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\BuildUsers' => __DIR__ . '/../..' . '/src/ChangeTrack/Snapshot/BuildUsers.php',
190
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\Collate' => __DIR__ . '/../..' . '/src/ChangeTrack/Snapshot/Collate.php',
191
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\ChangeTrack\\Snapshot\\SnapshotsConsumer' => __DIR__ . '/../..' . '/src/ChangeTrack/Snapshot/SnapshotsConsumer.php',
192
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Crons\\StandardCron' => __DIR__ . '/../..' . '/src/Crons/StandardCron.php',
193
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\Delete' => __DIR__ . '/../..' . '/src/Databases/AdminNotes/Delete.php',
194
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\AdminNotes\\EntryVO' => __DIR__ . '/../..' . '/src/Databases/AdminNotes/EntryVO.php',
209
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Insert' => __DIR__ . '/../..' . '/src/Databases/Base/Insert.php',
210
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Select' => __DIR__ . '/../..' . '/src/Databases/Base/Select.php',
211
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Base\\Update' => __DIR__ . '/../..' . '/src/Databases/Base/Update.php',
212
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Delete' => __DIR__ . '/../..' . '/src/Databases/ChangeTracking/Delete.php',
213
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\EntryVO' => __DIR__ . '/../..' . '/src/Databases/ChangeTracking/EntryVO.php',
214
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Handler' => __DIR__ . '/../..' . '/src/Databases/ChangeTracking/Handler.php',
215
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Insert' => __DIR__ . '/../..' . '/src/Databases/ChangeTracking/Insert.php',
216
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Select' => __DIR__ . '/../..' . '/src/Databases/ChangeTracking/Select.php',
217
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\ChangeTracking\\Update' => __DIR__ . '/../..' . '/src/Databases/ChangeTracking/Update.php',
218
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Comments\\Delete' => __DIR__ . '/../..' . '/src/Databases/Comments/Delete.php',
219
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Comments\\EntryVO' => __DIR__ . '/../..' . '/src/Databases/Comments/EntryVO.php',
220
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Comments\\Handler' => __DIR__ . '/../..' . '/src/Databases/Comments/Handler.php',
253
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Databases\\Traffic\\Select' => __DIR__ . '/../..' . '/src/Databases/Traffic/Select.php',
254
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\License\\EddLicenseVO' => __DIR__ . '/../..' . '/src/License/EddLicenseVO.php',
255
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\ModConsumer' => __DIR__ . '/../..' . '/src/Modules/ModConsumer.php',
256
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\MouseTrap\\Base' => __DIR__ . '/../..' . '/src/Modules/MouseTrap/Base.php',
257
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\MouseTrap\\Detect404' => __DIR__ . '/../..' . '/src/Modules/MouseTrap/Detect404.php',
258
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\MouseTrap\\DetectXmlRpc' => __DIR__ . '/../..' . '/src/Modules/MouseTrap/DetectXmlRpc.php',
259
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\MouseTrap\\FakeWebCrawler' => __DIR__ . '/../..' . '/src/Modules/MouseTrap/FakeWebCrawler.php',
260
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\MouseTrap\\InvalidUsername' => __DIR__ . '/../..' . '/src/Modules/MouseTrap/InvalidUsername.php',
261
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\MouseTrap\\LinkCheese' => __DIR__ . '/../..' . '/src/Modules/MouseTrap/LinkCheese.php',
262
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\OptsConsumer' => __DIR__ . '/../..' . '/src/Modules/OptsConsumer.php',
263
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\PluginControllerConsumer' => __DIR__ . '/../..' . '/src/Modules/PluginControllerConsumer.php',
264
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\Suspend\\Base' => __DIR__ . '/../..' . '/src/Modules/UserManagement/Suspend/Base.php',
265
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\Suspend\\Idle' => __DIR__ . '/../..' . '/src/Modules/UserManagement/Suspend/Idle.php',
266
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\Suspend\\PasswordExpiry' => __DIR__ . '/../..' . '/src/Modules/UserManagement/Suspend/PasswordExpiry.php',
267
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\Suspend\\Suspended' => __DIR__ . '/../..' . '/src/Modules/UserManagement/Suspend/Suspended.php',
268
+ 'FernleafSystems\\Wordpress\\Plugin\\Shield\\Modules\\UserManagement\\UpdateUserPasswordMeta' => __DIR__ . '/../..' . '/src/Modules/UserManagement/UpdateUserPasswordMeta.php',
269
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ConvertResultsToVos' => __DIR__ . '/../..' . '/src/Scans/Apc/ConvertResultsToVos.php',
270
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ConvertVosToResults' => __DIR__ . '/../..' . '/src/Scans/Apc/ConvertVosToResults.php',
271
  'FernleafSystems\\Wordpress\\Plugin\\Shield\\Scans\\Apc\\ResultItem' => __DIR__ . '/../..' . '/src/Scans/Apc/ResultItem.php',
378
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Data' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Data.php',
379
  'FernleafSystems\\Wordpress\\Services\\Utilities\\DataManipulation' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/DataManipulation.php',
380
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Email' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Email.php',
381
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\Encrypt\\OpenSslEncrypt' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncrypt.php',
382
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\Encrypt\\OpenSslEncryptVo' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncryptVo.php',
383
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\ReadDataFromFileEncrypted' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/File/ReadDataFromFileEncrypted.php',
384
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\TestFileWritable' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/File/TestFileWritable.php',
385
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\File\\WriteDataToFileEncrypted' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/File/WriteDataToFileEncrypted.php',
386
  'FernleafSystems\\Wordpress\\Services\\Utilities\\GeoIp' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/GeoIp.php',
387
  'FernleafSystems\\Wordpress\\Services\\Utilities\\HttpRequest' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/HttpRequest.php',
388
  'FernleafSystems\\Wordpress\\Services\\Utilities\\IpUtils' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/IpUtils.php',
389
+ 'FernleafSystems\\Wordpress\\Services\\Utilities\\Net\\VisitorIpDetection' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Net/VisitorIpDetection.php',
390
  'FernleafSystems\\Wordpress\\Services\\Utilities\\PluginUserMeta' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/PluginUserMeta.php',
391
  'FernleafSystems\\Wordpress\\Services\\Utilities\\Render' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/Render.php',
392
  'FernleafSystems\\Wordpress\\Services\\Utilities\\ServiceProviders' => __DIR__ . '/..' . '/fernleafsystems/wordpress-services/src/Utilities/ServiceProviders.php',
450
  'ICWP_WPSF_FeatureHandler_License' => __DIR__ . '/../..' . '/../features/license.php',
451
  'ICWP_WPSF_FeatureHandler_Lockdown' => __DIR__ . '/../..' . '/../features/lockdown.php',
452
  'ICWP_WPSF_FeatureHandler_LoginProtect' => __DIR__ . '/../..' . '/../features/login_protect.php',
453
+ 'ICWP_WPSF_FeatureHandler_Mousetrap' => __DIR__ . '/../..' . '/../features/mousetrap.php',
454
  'ICWP_WPSF_FeatureHandler_Plugin' => __DIR__ . '/../..' . '/../features/plugin.php',
455
  'ICWP_WPSF_FeatureHandler_Sessions' => __DIR__ . '/../..' . '/../features/sessions.php',
456
  'ICWP_WPSF_FeatureHandler_Statistics' => __DIR__ . '/../..' . '/../features/statistics.php',
466
  'ICWP_WPSF_Processor_AdminAccess_Whitelabel' => __DIR__ . '/../..' . '/../processors/adminaccess_whitelabel.php',
467
  'ICWP_WPSF_Processor_AuditTrail' => __DIR__ . '/../..' . '/../processors/audit_trail.php',
468
  'ICWP_WPSF_Processor_AuditTrail_Auditor' => __DIR__ . '/../..' . '/../processors/audit_trail_auditor.php',
469
+ 'ICWP_WPSF_Processor_AuditTrail_ChangeTracking' => __DIR__ . '/../..' . '/../processors/audit_trail_changetracking.php',
470
  'ICWP_WPSF_Processor_AuditTrail_Emails' => __DIR__ . '/../..' . '/../processors/audit_trail_emails.php',
471
  'ICWP_WPSF_Processor_AuditTrail_Plugins' => __DIR__ . '/../..' . '/../processors/audit_trail_plugins.php',
472
  'ICWP_WPSF_Processor_AuditTrail_Posts' => __DIR__ . '/../..' . '/../processors/audit_trail_posts.php',
512
  'ICWP_WPSF_Processor_LoginProtect_TwoFactorAuth' => __DIR__ . '/../..' . '/../processors/loginprotect_intentprovider_email.php',
513
  'ICWP_WPSF_Processor_LoginProtect_WpLogin' => __DIR__ . '/../..' . '/../processors/loginprotect_wplogin.php',
514
  'ICWP_WPSF_Processor_LoginProtect_Yubikey' => __DIR__ . '/../..' . '/../processors/loginprotect_intentprovider_yubikey.php',
515
+ 'ICWP_WPSF_Processor_Mousetrap' => __DIR__ . '/../..' . '/../processors/mousetrap.php',
516
  'ICWP_WPSF_Processor_Plugin' => __DIR__ . '/../..' . '/../processors/plugin.php',
517
  'ICWP_WPSF_Processor_Plugin_Badge' => __DIR__ . '/../..' . '/../processors/plugin_badge.php',
518
  'ICWP_WPSF_Processor_Plugin_BadgeWidget' => __DIR__ . '/../..' . '/../processors/plugin_badgewidget.php',
519
  'ICWP_WPSF_Processor_Plugin_CronDaily' => __DIR__ . '/../..' . '/../processors/plugin_crondaily.php',
520
+ 'ICWP_WPSF_Processor_Plugin_CronHourly' => __DIR__ . '/../..' . '/../processors/plugin_cronhourly.php',
521
  'ICWP_WPSF_Processor_Plugin_ImportExport' => __DIR__ . '/../..' . '/../processors/plugin_importexport.php',
522
  'ICWP_WPSF_Processor_Plugin_Notes' => __DIR__ . '/../..' . '/../processors/plugin_notes.php',
523
  'ICWP_WPSF_Processor_Plugin_Tracking' => __DIR__ . '/../..' . '/../processors/plugin_tracking.php',
531
  'ICWP_WPSF_Processor_UserManagement' => __DIR__ . '/../..' . '/../processors/user_management.php',
532
  'ICWP_WPSF_Processor_UserManagement_Passwords' => __DIR__ . '/../..' . '/../processors/usermanagement_passwords.php',
533
  'ICWP_WPSF_Processor_UserManagement_Sessions' => __DIR__ . '/../..' . '/../processors/usermanagement_sessions.php',
534
+ 'ICWP_WPSF_Processor_UserManagement_Suspend' => __DIR__ . '/../..' . '/../processors/usermanagement_suspend.php',
535
  'ICWP_WPSF_Query_Statistics_Base' => __DIR__ . '/../..' . '/../query/base/statistics_base.php',
536
  'ICWP_WPSF_Query_Statistics_Consolidation' => __DIR__ . '/../..' . '/../query/statistics/consolidation.php',
537
  'ICWP_WPSF_Query_Statistics_Reporting' => __DIR__ . '/../..' . '/../query/statistics/reporting.php',
715
  'Twig\\Node\\BlockReferenceNode' => __DIR__ . '/..' . '/twig/twig/src/Node/BlockReferenceNode.php',
716
  'Twig\\Node\\BodyNode' => __DIR__ . '/..' . '/twig/twig/src/Node/BodyNode.php',
717
  'Twig\\Node\\CheckSecurityNode' => __DIR__ . '/..' . '/twig/twig/src/Node/CheckSecurityNode.php',
718
+ 'Twig\\Node\\CheckToStringNode' => __DIR__ . '/..' . '/twig/twig/src/Node/CheckToStringNode.php',
719
  'Twig\\Node\\DeprecatedNode' => __DIR__ . '/..' . '/twig/twig/src/Node/DeprecatedNode.php',
720
  'Twig\\Node\\DoNode' => __DIR__ . '/..' . '/twig/twig/src/Node/DoNode.php',
721
  'Twig\\Node\\EmbedNode' => __DIR__ . '/..' . '/twig/twig/src/Node/EmbedNode.php',
src/lib/vendor/composer/installed.json CHANGED
@@ -148,66 +148,6 @@
148
  "maxmind"
149
  ]
150
  },
151
- {
152
- "name": "symfony/polyfill-ctype",
153
- "version": "v1.10.0",
154
- "version_normalized": "1.10.0.0",
155
- "source": {
156
- "type": "git",
157
- "url": "https://github.com/symfony/polyfill-ctype.git",
158
- "reference": "e3d826245268269cd66f8326bd8bc066687b4a19"
159
- },
160
- "dist": {
161
- "type": "zip",
162
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19",
163
- "reference": "e3d826245268269cd66f8326bd8bc066687b4a19",
164
- "shasum": ""
165
- },
166
- "require": {
167
- "php": ">=5.3.3"
168
- },
169
- "suggest": {
170
- "ext-ctype": "For best performance"
171
- },
172
- "time": "2018-08-06T14:22:27+00:00",
173
- "type": "library",
174
- "extra": {
175
- "branch-alias": {
176
- "dev-master": "1.9-dev"
177
- }
178
- },
179
- "installation-source": "dist",
180
- "autoload": {
181
- "psr-4": {
182
- "Symfony\\Polyfill\\Ctype\\": ""
183
- },
184
- "files": [
185
- "bootstrap.php"
186
- ]
187
- },
188
- "notification-url": "https://packagist.org/downloads/",
189
- "license": [
190
- "MIT"
191
- ],
192
- "authors": [
193
- {
194
- "name": "Symfony Community",
195
- "homepage": "https://symfony.com/contributors"
196
- },
197
- {
198
- "name": "Gert de Pagter",
199
- "email": "BackEndTea@gmail.com"
200
- }
201
- ],
202
- "description": "Symfony polyfill for ctype functions",
203
- "homepage": "https://symfony.com",
204
- "keywords": [
205
- "compatibility",
206
- "ctype",
207
- "polyfill",
208
- "portable"
209
- ]
210
- },
211
  {
212
  "name": "soundasleep/html2text",
213
  "version": "0.5.0",
@@ -363,67 +303,6 @@
363
  "dependency injection"
364
  ]
365
  },
366
- {
367
- "name": "symfony/polyfill-mbstring",
368
- "version": "v1.10.0",
369
- "version_normalized": "1.10.0.0",
370
- "source": {
371
- "type": "git",
372
- "url": "https://github.com/symfony/polyfill-mbstring.git",
373
- "reference": "c79c051f5b3a46be09205c73b80b346e4153e494"
374
- },
375
- "dist": {
376
- "type": "zip",
377
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
378
- "reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
379
- "shasum": ""
380
- },
381
- "require": {
382
- "php": ">=5.3.3"
383
- },
384
- "suggest": {
385
- "ext-mbstring": "For best performance"
386
- },
387
- "time": "2018-09-21T13:07:52+00:00",
388
- "type": "library",
389
- "extra": {
390
- "branch-alias": {
391
- "dev-master": "1.9-dev"
392
- }
393
- },
394
- "installation-source": "dist",
395
- "autoload": {
396
- "psr-4": {
397
- "Symfony\\Polyfill\\Mbstring\\": ""
398
- },
399
- "files": [
400
- "bootstrap.php"
401
- ]
402
- },
403
- "notification-url": "https://packagist.org/downloads/",
404
- "license": [
405
- "MIT"
406
- ],
407
- "authors": [
408
- {
409
- "name": "Nicolas Grekas",
410
- "email": "p@tchwork.com"
411
- },
412
- {
413
- "name": "Symfony Community",
414
- "homepage": "https://symfony.com/contributors"
415
- }
416
- ],
417
- "description": "Symfony polyfill for the Mbstring extension",
418
- "homepage": "https://symfony.com",
419
- "keywords": [
420
- "compatibility",
421
- "mbstring",
422
- "polyfill",
423
- "portable",
424
- "shim"
425
- ]
426
- },
427
  {
428
  "name": "google/recaptcha",
429
  "version": "1.1.2",
@@ -707,74 +586,6 @@
707
  "maxmind"
708
  ]
709
  },
710
- {
711
- "name": "twig/twig",
712
- "version": "v1.37.1",
713
- "version_normalized": "1.37.1.0",
714
- "source": {
715
- "type": "git",
716
- "url": "https://github.com/twigphp/Twig.git",
717
- "reference": "66be9366c76cbf23e82e7171d47cbfa54a057a62"
718
- },
719
- "dist": {
720
- "type": "zip",
721
- "url": "https://api.github.com/repos/twigphp/Twig/zipball/66be9366c76cbf23e82e7171d47cbfa54a057a62",
722
- "reference": "66be9366c76cbf23e82e7171d47cbfa54a057a62",
723
- "shasum": ""
724
- },
725
- "require": {
726
- "php": ">=5.4.0",
727
- "symfony/polyfill-ctype": "^1.8"
728
- },
729
- "require-dev": {
730
- "psr/container": "^1.0",
731
- "symfony/debug": "^2.7",
732
- "symfony/phpunit-bridge": "^3.4.19|^4.1.8"
733
- },
734
- "time": "2019-01-14T14:59:29+00:00",
735
- "type": "library",
736
- "extra": {
737
- "branch-alias": {
738
- "dev-master": "1.37-dev"
739
- }
740
- },
741
- "installation-source": "dist",
742
- "autoload": {
743
- "psr-0": {
744
- "Twig_": "lib/"
745
- },
746
- "psr-4": {
747
- "Twig\\": "src/"
748
- }
749
- },
750
- "notification-url": "https://packagist.org/downloads/",
751
- "license": [
752
- "BSD-3-Clause"
753
- ],
754
- "authors": [
755
- {
756
- "name": "Fabien Potencier",
757
- "email": "fabien@symfony.com",
758
- "homepage": "http://fabien.potencier.org",
759
- "role": "Lead Developer"
760
- },
761
- {
762
- "name": "Armin Ronacher",
763
- "email": "armin.ronacher@active-4.com",
764
- "role": "Project Founder"
765
- },
766
- {
767
- "name": "Twig Team",
768
- "homepage": "https://twig.symfony.com/contributors",
769
- "role": "Contributors"
770
- }
771
- ],
772
- "description": "Twig, the flexible, fast, and secure template language for PHP",
773
- "homepage": "https://twig.symfony.com",
774
- "keywords": [
775
- "templating"
776
- ]
777
- },
778
  {
779
  "name": "composer/ca-bundle",
780
  "version": "1.1.4",
@@ -869,6 +680,195 @@
869
  ],
870
  "description": "Collection of simple utilities and traits"
871
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
872
  {
873
  "name": "fernleafsystems/wordpress-services",
874
  "version": "dev-develop",
@@ -876,12 +876,12 @@
876
  "source": {
877
  "type": "git",
878
  "url": "https://bitbucket.org/FernleafSystems/wordpress-services.git",
879
- "reference": "a510c091d52913b5eeefc5183702b2778ca7dfac"
880
  },
881
  "dist": {
882
  "type": "zip",
883
- "url": "https://bitbucket.org/FernleafSystems/wordpress-services/get/a510c091d52913b5eeefc5183702b2778ca7dfac.zip",
884
- "reference": "a510c091d52913b5eeefc5183702b2778ca7dfac",
885
  "shasum": ""
886
  },
887
  "require": {
@@ -894,7 +894,7 @@
894
  "symfony/yaml": "~2.0||~3.0",
895
  "twig/twig": "^1.0"
896
  },
897
- "time": "2019-02-22T14:24:04+00:00",
898
  "type": "library",
899
  "installation-source": "source",
900
  "autoload": {
148
  "maxmind"
149
  ]
150
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  {
152
  "name": "soundasleep/html2text",
153
  "version": "0.5.0",
303
  "dependency injection"
304
  ]
305
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306
  {
307
  "name": "google/recaptcha",
308
  "version": "1.1.2",
586
  "maxmind"
587
  ]
588
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
589
  {
590
  "name": "composer/ca-bundle",
591
  "version": "1.1.4",
680
  ],
681
  "description": "Collection of simple utilities and traits"
682
  },
683
+ {
684
+ "name": "symfony/polyfill-ctype",
685
+ "version": "v1.11.0",
686
+ "version_normalized": "1.11.0.0",
687
+ "source": {
688
+ "type": "git",
689
+ "url": "https://github.com/symfony/polyfill-ctype.git",
690
+ "reference": "82ebae02209c21113908c229e9883c419720738a"
691
+ },
692
+ "dist": {
693
+ "type": "zip",
694
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a",
695
+ "reference": "82ebae02209c21113908c229e9883c419720738a",
696
+ "shasum": ""
697
+ },
698
+ "require": {
699
+ "php": ">=5.3.3"
700
+ },
701
+ "suggest": {
702
+ "ext-ctype": "For best performance"
703
+ },
704
+ "time": "2019-02-06T07:57:58+00:00",
705
+ "type": "library",
706
+ "extra": {
707
+ "branch-alias": {
708
+ "dev-master": "1.11-dev"
709
+ }
710
+ },
711
+ "installation-source": "dist",
712
+ "autoload": {
713
+ "psr-4": {
714
+ "Symfony\\Polyfill\\Ctype\\": ""
715
+ },
716
+ "files": [
717
+ "bootstrap.php"
718
+ ]
719
+ },
720
+ "notification-url": "https://packagist.org/downloads/",
721
+ "license": [
722
+ "MIT"
723
+ ],
724
+ "authors": [
725
+ {
726
+ "name": "Symfony Community",
727
+ "homepage": "https://symfony.com/contributors"
728
+ },
729
+ {
730
+ "name": "Gert de Pagter",
731
+ "email": "BackEndTea@gmail.com"
732
+ }
733
+ ],
734
+ "description": "Symfony polyfill for ctype functions",
735
+ "homepage": "https://symfony.com",
736
+ "keywords": [
737
+ "compatibility",
738
+ "ctype",
739
+ "polyfill",
740
+ "portable"
741
+ ]
742
+ },
743
+ {
744
+ "name": "symfony/polyfill-mbstring",
745
+ "version": "v1.11.0",
746
+ "version_normalized": "1.11.0.0",
747
+ "source": {
748
+ "type": "git",
749
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
750
+ "reference": "fe5e94c604826c35a32fa832f35bd036b6799609"
751
+ },
752
+ "dist": {
753
+ "type": "zip",
754
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609",
755
+ "reference": "fe5e94c604826c35a32fa832f35bd036b6799609",
756
+ "shasum": ""
757
+ },
758
+ "require": {
759
+ "php": ">=5.3.3"
760
+ },
761
+ "suggest": {
762
+ "ext-mbstring": "For best performance"
763
+ },
764
+ "time": "2019-02-06T07:57:58+00:00",
765
+ "type": "library",
766
+ "extra": {
767
+ "branch-alias": {
768
+ "dev-master": "1.11-dev"
769
+ }
770
+ },
771
+ "installation-source": "dist",
772
+ "autoload": {
773
+ "psr-4": {
774
+ "Symfony\\Polyfill\\Mbstring\\": ""
775
+ },
776
+ "files": [
777
+ "bootstrap.php"
778
+ ]
779
+ },
780
+ "notification-url": "https://packagist.org/downloads/",
781
+ "license": [
782
+ "MIT"
783
+ ],
784
+ "authors": [
785
+ {
786
+ "name": "Nicolas Grekas",
787
+ "email": "p@tchwork.com"
788
+ },
789
+ {
790
+ "name": "Symfony Community",
791
+ "homepage": "https://symfony.com/contributors"
792
+ }
793
+ ],
794
+ "description": "Symfony polyfill for the Mbstring extension",
795
+ "homepage": "https://symfony.com",
796
+ "keywords": [
797
+ "compatibility",
798
+ "mbstring",
799
+ "polyfill",
800
+ "portable",
801
+ "shim"
802
+ ]
803
+ },
804
+ {
805
+ "name": "twig/twig",
806
+ "version": "v1.38.4",
807
+ "version_normalized": "1.38.4.0",
808
+ "source": {
809
+ "type": "git",
810
+ "url": "https://github.com/twigphp/Twig.git",
811
+ "reference": "7732e9e7017d751313811bd118de61302e9c8b35"
812
+ },
813
+ "dist": {
814
+ "type": "zip",
815
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/7732e9e7017d751313811bd118de61302e9c8b35",
816
+ "reference": "7732e9e7017d751313811bd118de61302e9c8b35",
817
+ "shasum": ""
818
+ },
819
+ "require": {
820
+ "php": ">=5.4.0",
821
+ "symfony/polyfill-ctype": "^1.8"
822
+ },
823
+ "require-dev": {
824
+ "psr/container": "^1.0",
825
+ "symfony/debug": "^2.7",
826
+ "symfony/phpunit-bridge": "^3.4.19|^4.1.8"
827
+ },
828
+ "time": "2019-03-23T14:27:19+00:00",
829
+ "type": "library",
830
+ "extra": {
831
+ "branch-alias": {
832
+ "dev-master": "1.38-dev"
833
+ }
834
+ },
835
+ "installation-source": "dist",
836
+ "autoload": {
837
+ "psr-0": {
838
+ "Twig_": "lib/"
839
+ },
840
+ "psr-4": {
841
+ "Twig\\": "src/"
842
+ }
843
+ },
844
+ "notification-url": "https://packagist.org/downloads/",
845
+ "license": [
846
+ "BSD-3-Clause"
847
+ ],
848
+ "authors": [
849
+ {
850
+ "name": "Fabien Potencier",
851
+ "email": "fabien@symfony.com",
852
+ "homepage": "http://fabien.potencier.org",
853
+ "role": "Lead Developer"
854
+ },
855
+ {
856
+ "name": "Armin Ronacher",
857
+ "email": "armin.ronacher@active-4.com",
858
+ "role": "Project Founder"
859
+ },
860
+ {
861
+ "name": "Twig Team",
862
+ "homepage": "https://twig.symfony.com/contributors",
863
+ "role": "Contributors"
864
+ }
865
+ ],
866
+ "description": "Twig, the flexible, fast, and secure template language for PHP",
867
+ "homepage": "https://twig.symfony.com",
868
+ "keywords": [
869
+ "templating"
870
+ ]
871
+ },
872
  {
873
  "name": "fernleafsystems/wordpress-services",
874
  "version": "dev-develop",
876
  "source": {
877
  "type": "git",
878
  "url": "https://bitbucket.org/FernleafSystems/wordpress-services.git",
879
+ "reference": "1dfc3b46711bd27c0fcca6dbfda00307ae042beb"
880
  },
881
  "dist": {
882
  "type": "zip",
883
+ "url": "https://bitbucket.org/FernleafSystems/wordpress-services/get/1dfc3b46711bd27c0fcca6dbfda00307ae042beb.zip",
884
+ "reference": "1dfc3b46711bd27c0fcca6dbfda00307ae042beb",
885
  "shasum": ""
886
  },
887
  "require": {
894
  "symfony/yaml": "~2.0||~3.0",
895
  "twig/twig": "^1.0"
896
  },
897
+ "time": "2019-03-23T15:40:07+00:00",
898
  "type": "library",
899
  "installation-source": "source",
900
  "autoload": {
src/lib/vendor/fernleafsystems/wordpress-services/src/Core/CoreFileHashes.php CHANGED
@@ -41,7 +41,7 @@ class CoreFileHashes {
41
  */
42
  public function getFileFragment( $sFile ) {
43
  $sNorm = wp_normalize_path( $sFile );
44
- return path_is_absolute( $sFile ) ? str_replace( ABSPATH, '', $sNorm ) : $sNorm;
45
  }
46
 
47
  /**
@@ -75,4 +75,4 @@ class CoreFileHashes {
75
  public function isReady() {
76
  return ( count( $this->getHashes() ) > 0 );
77
  }
78
- }
41
  */
42
  public function getFileFragment( $sFile ) {
43
  $sNorm = wp_normalize_path( $sFile );
44
+ return path_is_absolute( $sFile ) ? str_replace( wp_normalize_path( ABSPATH ), '', $sNorm ) : $sNorm;
45
  }
46
 
47
  /**
75
  public function isReady() {
76
  return ( count( $this->getHashes() ) > 0 );
77
  }
78
+ }
src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Fs.php CHANGED
@@ -15,11 +15,6 @@ class Fs {
15
  */
16
  protected $oWpfs = null;
17
 
18
- /**
19
- * @var string
20
- */
21
- protected $sWpConfigPath = null;
22
-
23
  /**
24
  * @param string $sBase
25
  * @param string $sPath
@@ -126,18 +121,11 @@ class Fs {
126
  return $oIterator;
127
  }
128
 
129
- protected function setWpConfigPath() {
130
- $this->sWpConfigPath = ABSPATH.'wp-config.php';
131
- if ( !$this->exists( $this->sWpConfigPath ) ) {
132
- $this->sWpConfigPath = ABSPATH.'..'.DIRECTORY_SEPARATOR.'wp-config.php';
133
- if ( !$this->exists( $this->sWpConfigPath ) ) {
134
- $this->sWpConfigPath = false;
135
- }
136
- }
137
- }
138
-
139
  public function getContent_WpConfig() {
140
- return $this->getFileContent( $this->sWpConfigPath );
141
  }
142
 
143
  /**
@@ -145,7 +133,7 @@ class Fs {
145
  * @return bool
146
  */
147
  public function putContent_WpConfig( $sContent ) {
148
- return $this->putFileContent( $this->sWpConfigPath, $sContent );
149
  }
150
 
151
  /**
@@ -159,13 +147,6 @@ class Fs {
159
  return Services::HttpRequest()->get( $sUrl );
160
  }
161
 
162
- /**
163
- * @return string
164
- */
165
- public function getWpConfigPath() {
166
- return $this->sWpConfigPath;
167
- }
168
-
169
  /**
170
  * @return bool
171
  */
@@ -418,23 +399,42 @@ class Fs {
418
  }
419
 
420
  /**
421
- * @param $sFilePath
 
 
 
 
 
 
 
 
 
 
 
 
422
  * @return bool|mixed
423
  */
424
- public function isFile( $sFilePath ) {
425
  $oFs = $this->getWpfs();
426
- if ( $oFs && $oFs->is_file( $sFilePath ) ) {
427
  return true;
428
  }
429
- return function_exists( 'is_file' ) ? is_file( $sFilePath ) : null;
430
  }
431
 
432
  /**
433
- * @param $sDirPath
434
  * @return bool
435
  */
436
- public function mkdir( $sDirPath ) {
437
- return wp_mkdir_p( $sDirPath );
 
 
 
 
 
 
 
 
438
  }
439
 
440
  /**
@@ -466,7 +466,7 @@ class Fs {
466
  if ( is_null( $this->oWpfs ) ) {
467
  $this->oWpfs = false;
468
  require_once( ABSPATH.'wp-admin/includes/file.php' );
469
- if ( WP_Filesystem() ) {
470
  global $wp_filesystem;
471
  if ( isset( $wp_filesystem ) && is_object( $wp_filesystem ) ) {
472
  $this->oWpfs = $wp_filesystem;
@@ -514,4 +514,12 @@ class Fs {
514
  public function postUrl( $sUrl, $aRequestArgs = array() ) {
515
  return Services::HttpRequest()->requestUrl( $sUrl, $aRequestArgs, 'POST' );
516
  }
 
 
 
 
 
 
 
 
517
  }
15
  */
16
  protected $oWpfs = null;
17
 
 
 
 
 
 
18
  /**
19
  * @param string $sBase
20
  * @param string $sPath
121
  return $oIterator;
122
  }
123
 
124
+ /**
125
+ * @return string|null
126
+ */
 
 
 
 
 
 
 
127
  public function getContent_WpConfig() {
128
+ return $this->getFileContent( Services::WpGeneral()->getPath_WpConfig() );
129
  }
130
 
131
  /**
133
  * @return bool
134
  */
135
  public function putContent_WpConfig( $sContent ) {
136
+ return $this->putFileContent( Services::WpGeneral()->getPath_WpConfig(), $sContent );
137
  }
138
 
139
  /**
147
  return Services::HttpRequest()->get( $sUrl );
148
  }
149
 
 
 
 
 
 
 
 
150
  /**
151
  * @return bool
152
  */
399
  }
400
 
401
  /**
402
+ * @param string $sPath
403
+ * @return bool
404
+ */
405
+ public function isDir( $sPath ) {
406
+ $oFs = $this->getWpfs();
407
+ if ( $oFs && $oFs->is_dir( $sPath ) ) {
408
+ return true;
409
+ }
410
+ return function_exists( 'is_dir' ) ? is_dir( $sPath ) : false;
411
+ }
412
+
413
+ /**
414
+ * @param $sPath
415
  * @return bool|mixed
416
  */
417
+ public function isFile( $sPath ) {
418
  $oFs = $this->getWpfs();
419
+ if ( $oFs && $oFs->is_file( $sPath ) ) {
420
  return true;
421
  }
422
+ return function_exists( 'is_file' ) ? is_file( $sPath ) : null;
423
  }
424
 
425
  /**
 
426
  * @return bool
427
  */
428
+ public function isFilesystemAccessDirect() {
429
+ return ( $this->getWpfs() instanceof \WP_Filesystem_Direct );
430
+ }
431
+
432
+ /**
433
+ * @param string $sPath
434
+ * @return bool
435
+ */
436
+ public function mkdir( $sPath ) {
437
+ return wp_mkdir_p( $sPath );
438
  }
439
 
440
  /**
466
  if ( is_null( $this->oWpfs ) ) {
467
  $this->oWpfs = false;
468
  require_once( ABSPATH.'wp-admin/includes/file.php' );
469
+ if ( \WP_Filesystem() ) {
470
  global $wp_filesystem;
471
  if ( isset( $wp_filesystem ) && is_object( $wp_filesystem ) ) {
472
  $this->oWpfs = $wp_filesystem;
514
  public function postUrl( $sUrl, $aRequestArgs = array() ) {
515
  return Services::HttpRequest()->requestUrl( $sUrl, $aRequestArgs, 'POST' );
516
  }
517
+
518
+ /**
519
+ * @deprecated
520
+ * @return string
521
+ */
522
+ public function getWpConfigPath() {
523
+ return Services::WpGeneral()->getPath_WpConfig();
524
+ }
525
  }
src/lib/vendor/fernleafsystems/wordpress-services/src/Core/General.php CHANGED
@@ -57,7 +57,7 @@ class General {
57
  wp_maybe_auto_update();
58
 
59
  if ( !empty( $sRedirect ) ) {
60
- $this->doRedirect( network_admin_url( $sRedirect ) );
61
  }
62
  return true;
63
  }
@@ -249,7 +249,7 @@ class General {
249
  * @return string
250
  */
251
  public function getTimeStampForDisplay( $nTime = null ) {
252
- $nTime = empty( $nTime ) ? Services::Request()->time() : $nTime;
253
  return date_i18n( DATE_RFC2822, $this->getTimeAsGmtOffset( $nTime ) );
254
  }
255
 
@@ -288,6 +288,16 @@ class General {
288
  return $mResult;
289
  }
290
 
 
 
 
 
 
 
 
 
 
 
291
  /**
292
  * @return bool
293
  */
@@ -421,20 +431,12 @@ class General {
421
  return $sUrl;
422
  }
423
 
424
- /**
425
- * @param string
426
- * @return string
427
- */
428
- public function getIsCurrentPage( $sPage ) {
429
- return $sPage == $this->getCurrentPage();
430
- }
431
-
432
  /**
433
  * @param string
434
  * @return string
435
  */
436
  public function getIsPage_Updates() {
437
- return $this->getIsCurrentPage( 'update.php' );
438
  }
439
 
440
  /**
@@ -490,28 +492,35 @@ class General {
490
  }
491
 
492
  /**
493
- * @return boolean
494
  */
495
  public function isAjax() {
496
  return defined( 'DOING_AJAX' ) && DOING_AJAX;
497
  }
498
 
499
  /**
500
- * @return boolean
501
  */
502
  public function isCron() {
503
  return defined( 'DOING_CRON' ) && DOING_CRON;
504
  }
505
 
506
  /**
507
- * @return boolean
508
  */
509
  public function isMobile() {
510
  return function_exists( 'wp_is_mobile' ) && wp_is_mobile();
511
  }
512
 
513
  /**
514
- * @return boolean
 
 
 
 
 
 
 
515
  */
516
  public function isXmlrpc() {
517
  return defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST;
@@ -616,7 +625,7 @@ class General {
616
  * @return string
617
  */
618
  public function getTimeStringForDisplay( $nTime = null, $bShowTime = true, $bShowDate = true ) {
619
- $nTime = empty( $nTime ) ? Services::Request()->time() : $nTime;
620
 
621
  $sFullTimeString = $bShowTime ? $this->getTimeFormat() : '';
622
  if ( empty( $sFullTimeString ) ) {
@@ -642,7 +651,7 @@ class General {
642
  }
643
  }
644
 
645
- $nTime = empty( $nTime ) ? Services::Request()->time() : $nTime;
646
  return $nTime + ( $nTimezoneOffset*HOUR_IN_SECONDS );
647
  }
648
 
@@ -750,17 +759,7 @@ class General {
750
  * @return bool|string
751
  */
752
  public function getIsPluginInstalled( $sCompareString, $sKey = 'Name' ) {
753
- $aPlugins = $this->getPlugins();
754
- if ( empty( $aPlugins ) || !is_array( $aPlugins ) ) {
755
- return false;
756
- }
757
-
758
- foreach ( $aPlugins as $sBaseFileName => $aPluginData ) {
759
- if ( isset( $aPluginData[ $sKey ] ) && $sCompareString == $aPluginData[ $sKey ] ) {
760
- return $sBaseFileName;
761
- }
762
- }
763
- return false;
764
  }
765
 
766
  /**
@@ -835,7 +834,7 @@ class General {
835
  /**
836
  * @deprecated
837
  * @param string $sRootPluginFile - the full path to the root plugin file
838
- * @return \stdClass
839
  */
840
  public function getPluginData( $sRootPluginFile ) {
841
  return Services::WpPlugins()->getExtendedData( $sRootPluginFile );
@@ -875,11 +874,7 @@ class General {
875
  * @return bool
876
  */
877
  public function getIsPluginActive( $sCompareString, $sKey = 'Name' ) {
878
- $sPluginFile = $this->getIsPluginInstalled( $sCompareString, $sKey );
879
- if ( !$sPluginFile ) {
880
- return false;
881
- }
882
- return is_plugin_active( $sPluginFile ) ? $sPluginFile : false;
883
  }
884
 
885
  /**
@@ -1045,6 +1040,15 @@ class General {
1045
  return Services::WpUsers()->getAllUserLoginUsernames();
1046
  }
1047
 
 
 
 
 
 
 
 
 
 
1048
  /**
1049
  * @deprecated
1050
  * @param string $sUrl
@@ -1060,7 +1064,7 @@ class General {
1060
  * @deprecated
1061
  */
1062
  public function redirectHere() {
1063
- $this->doRedirect( Services::Request()->getUri() );
1064
  }
1065
 
1066
  /**
@@ -1068,7 +1072,7 @@ class General {
1068
  * @param array $aQueryParams
1069
  */
1070
  public function redirectToLogin( $aQueryParams = array() ) {
1071
- $this->doRedirect( wp_login_url(), $aQueryParams );
1072
  }
1073
 
1074
  /**
@@ -1076,7 +1080,7 @@ class General {
1076
  * @param array $aQueryParams
1077
  */
1078
  public function redirectToAdmin( $aQueryParams = array() ) {
1079
- $this->doRedirect( is_multisite() ? get_admin_url() : admin_url(), $aQueryParams );
1080
  }
1081
 
1082
  /**
@@ -1084,6 +1088,6 @@ class General {
1084
  * @param array $aQueryParams
1085
  */
1086
  public function redirectToHome( $aQueryParams = array() ) {
1087
- $this->doRedirect( home_url(), $aQueryParams );
1088
  }
1089
  }
57
  wp_maybe_auto_update();
58
 
59
  if ( !empty( $sRedirect ) ) {
60
+ Services::Response()->redirect( network_admin_url( $sRedirect ) );
61
  }
62
  return true;
63
  }
249
  * @return string
250
  */
251
  public function getTimeStampForDisplay( $nTime = null ) {
252
+ $nTime = empty( $nTime ) ? Services::Request()->ts() : $nTime;
253
  return date_i18n( DATE_RFC2822, $this->getTimeAsGmtOffset( $nTime ) );
254
  }
255
 
288
  return $mResult;
289
  }
290
 
291
+ /**
292
+ * @return string|null
293
+ */
294
+ public function getPath_WpConfig() {
295
+ $oFs = Services::WpFs();
296
+ $sMain = path_join( ABSPATH, 'wp-config.php' );
297
+ $sSec = path_join( ABSPATH.'..', 'wp-config.php' );
298
+ return $oFs->exists( $sMain ) ? $sMain : ( $oFs->exists( $sSec ) ? $sSec : null );
299
+ }
300
+
301
  /**
302
  * @return bool
303
  */
431
  return $sUrl;
432
  }
433
 
 
 
 
 
 
 
 
 
434
  /**
435
  * @param string
436
  * @return string
437
  */
438
  public function getIsPage_Updates() {
439
+ return Services::WpPost()->isCurrentPage( 'update.php' );
440
  }
441
 
442
  /**
492
  }
493
 
494
  /**
495
+ * @return bool
496
  */
497
  public function isAjax() {
498
  return defined( 'DOING_AJAX' ) && DOING_AJAX;
499
  }
500
 
501
  /**
502
+ * @return bool
503
  */
504
  public function isCron() {
505
  return defined( 'DOING_CRON' ) && DOING_CRON;
506
  }
507
 
508
  /**
509
+ * @return bool
510
  */
511
  public function isMobile() {
512
  return function_exists( 'wp_is_mobile' ) && wp_is_mobile();
513
  }
514
 
515
  /**
516
+ * @return bool
517
+ */
518
+ public function isWpCli() {
519
+ return defined( 'WP_CLI' ) && WP_CLI;
520
+ }
521
+
522
+ /**
523
+ * @return bool
524
  */
525
  public function isXmlrpc() {
526
  return defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST;
625
  * @return string
626
  */
627
  public function getTimeStringForDisplay( $nTime = null, $bShowTime = true, $bShowDate = true ) {
628
+ $nTime = empty( $nTime ) ? Services::Request()->ts() : $nTime;
629
 
630
  $sFullTimeString = $bShowTime ? $this->getTimeFormat() : '';
631
  if ( empty( $sFullTimeString ) ) {
651
  }
652
  }
653
 
654
+ $nTime = empty( $nTime ) ? Services::Request()->ts() : $nTime;
655
  return $nTime + ( $nTimezoneOffset*HOUR_IN_SECONDS );
656
  }
657
 
759
  * @return bool|string
760
  */
761
  public function getIsPluginInstalled( $sCompareString, $sKey = 'Name' ) {
762
+ return Services::WpPlugins()->isInstalled( Services::WpPlugins()->findPluginBy( $sCompareString, $sKey ) );
 
 
 
 
 
 
 
 
 
 
763
  }
764
 
765
  /**
834
  /**
835
  * @deprecated
836
  * @param string $sRootPluginFile - the full path to the root plugin file
837
+ * @return array
838
  */
839
  public function getPluginData( $sRootPluginFile ) {
840
  return Services::WpPlugins()->getExtendedData( $sRootPluginFile );
874
  * @return bool
875
  */
876
  public function getIsPluginActive( $sCompareString, $sKey = 'Name' ) {
877
+ return Services::WpPlugins()->isActive( Services::WpPlugins()->findPluginBy( $sCompareString, $sKey ) );
 
 
 
 
878
  }
879
 
880
  /**
1040
  return Services::WpUsers()->getAllUserLoginUsernames();
1041
  }
1042
 
1043
+ /**
1044
+ * @deprecated
1045
+ * @param string
1046
+ * @return string
1047
+ */
1048
+ public function getIsCurrentPage( $sPage ) {
1049
+ return Services::WpPost()->isCurrentPage( $sPage );
1050
+ }
1051
+
1052
  /**
1053
  * @deprecated
1054
  * @param string $sUrl
1064
  * @deprecated
1065
  */
1066
  public function redirectHere() {
1067
+ Services::Response()->redirectHere();
1068
  }
1069
 
1070
  /**
1072
  * @param array $aQueryParams
1073
  */
1074
  public function redirectToLogin( $aQueryParams = array() ) {
1075
+ Services::Response()->redirectToLogin( $aQueryParams );
1076
  }
1077
 
1078
  /**
1080
  * @param array $aQueryParams
1081
  */
1082
  public function redirectToAdmin( $aQueryParams = array() ) {
1083
+ Services::Response()->redirectToAdmin( $aQueryParams );
1084
  }
1085
 
1086
  /**
1088
  * @param array $aQueryParams
1089
  */
1090
  public function redirectToHome( $aQueryParams = array() ) {
1091
+ Services::Response()->redirectToHome( $aQueryParams );
1092
  }
1093
  }
src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Plugins.php CHANGED
@@ -219,7 +219,7 @@ class Plugins {
219
  protected function checkForUpdates() {
220
 
221
  if ( class_exists( 'WPRC_Installer' ) && method_exists( 'WPRC_Installer', 'wprc_update_plugins' ) ) {
222
- WPRC_Installer::wprc_update_plugins();
223
  return true;
224
  }
225
  else if ( function_exists( 'wp_update_plugins' ) ) {
@@ -373,6 +373,18 @@ class Plugins {
373
  return array_keys( $this->getPlugins() );
374
  }
375
 
 
 
 
 
 
 
 
 
 
 
 
 
376
  /**
377
  * @return array[]
378
  */
219
  protected function checkForUpdates() {
220
 
221
  if ( class_exists( 'WPRC_Installer' ) && method_exists( 'WPRC_Installer', 'wprc_update_plugins' ) ) {
222
+ \WPRC_Installer::wprc_update_plugins();
223
  return true;
224
  }
225
  else if ( function_exists( 'wp_update_plugins' ) ) {
373
  return array_keys( $this->getPlugins() );
374
  }
375
 
376
+ /**
377
+ * @return string[]
378
+ */
379
+ public function getInstalledWpOrgPluginFiles() {
380
+ return array_values( array_filter(
381
+ $this->getInstalledPluginFiles(),
382
+ function ( $sFile ) {
383
+ return $this->isWpOrg( $sFile );
384
+ }
385
+ ) );
386
+ }
387
+
388
  /**
389
  * @return array[]
390
  */
src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Request.php CHANGED
@@ -113,6 +113,13 @@ class Request {
113
  return $bIncludeCookie ? array_merge( $aParams, $this->aCookie ) : $aParams;
114
  }
115
 
 
 
 
 
 
 
 
116
  /**
117
  * @return string URI Path in lowercase
118
  */
113
  return $bIncludeCookie ? array_merge( $aParams, $this->aCookie ) : $aParams;
114
  }
115
 
116
+ /**
117
+ * @return string
118
+ */
119
+ public function getHost() {
120
+ return $this->server( 'HTTP_HOST' );
121
+ }
122
+
123
  /**
124
  * @return string URI Path in lowercase
125
  */
src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Respond.php CHANGED
@@ -17,7 +17,7 @@ class Respond {
17
  protected $oResponse;
18
 
19
  public function send() {
20
- if ( Services::WpGeneral()->getIsAjax() ) {
21
  $this->sendAjax();
22
  }
23
  else {
17
  protected $oResponse;
18
 
19
  public function send() {
20
+ if ( Services::WpGeneral()->isAjax() ) {
21
  $this->sendAjax();
22
  }
23
  else {
src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Response.php CHANGED
@@ -16,6 +16,20 @@ class Response {
16
  public function __construct() {
17
  }
18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  /**
20
  * @param string $sUrl
21
  * @param array $aQueryParams
16
  public function __construct() {
17
  }
18
 
19
+ /**
20
+ * @param string $sStringContent
21
+ * @param string $sFilename
22
+ * @return bool
23
+ */
24
+ public function downloadStringAsFile( $sStringContent, $sFilename ) {
25
+ header( "Content-type: application/octet-stream" );
26
+ header( "Content-disposition: attachment; filename=".$sFilename );
27
+ header( "Content-Transfer-Encoding: binary" );
28
+ header( "Content-Length: ".strlen( $sStringContent ) );
29
+ echo $sStringContent;
30
+ die();
31
+ }
32
+
33
  /**
34
  * @param string $sUrl
35
  * @param array $aQueryParams
src/lib/vendor/fernleafsystems/wordpress-services/src/Core/Users.php CHANGED
@@ -29,12 +29,21 @@ class Users {
29
  return $bSuccess;
30
  }
31
 
 
 
 
 
 
 
 
 
 
32
  /**
33
  * @param array $aLoginUrlParams
34
  */
35
  public function forceUserRelogin( $aLoginUrlParams = array() ) {
36
  $this->logoutUser();
37
- Services::WpGeneral()->redirectToLogin( $aLoginUrlParams );
38
  }
39
 
40
  /**
@@ -247,6 +256,13 @@ class Users {
247
  return $bIsAdmin;
248
  }
249
 
 
 
 
 
 
 
 
250
  /**
251
  * @return bool
252
  */
29
  return $bSuccess;
30
  }
31
 
32
+ /**
33
+ * @param string $sUsernameOrEmail
34
+ * @return bool
35
+ */
36
+ public function exists( $sUsernameOrEmail ) {
37
+ return ( $this->getUserByEmail( $sUsernameOrEmail ) instanceof \WP_User )
38
+ || ( $this->getUserByUsername( $sUsernameOrEmail ) instanceof \WP_User );
39
+ }
40
+
41
  /**
42
  * @param array $aLoginUrlParams
43
  */
44
  public function forceUserRelogin( $aLoginUrlParams = array() ) {
45
  $this->logoutUser();
46
+ Services::Response()->redirectToLogin( $aLoginUrlParams );
47
  }
48
 
49
  /**
256
  return $bIsAdmin;
257
  }
258
 
259
+ /**
260
+ * @return bool
261
+ */
262
+ public function isProfilePage() {
263
+ return defined( 'IS_PROFILE_PAGE' ) && IS_PROFILE_PAGE;
264
+ }
265
+
266
  /**
267
  * @return bool
268
  */
src/lib/vendor/fernleafsystems/wordpress-services/src/Services.php CHANGED
@@ -85,6 +85,9 @@ class Services {
85
  self::$oDic[ 'service_ip' ] = function () {
86
  return Utilities\IpUtils::GetInstance();
87
  };
 
 
 
88
  self::$oDic[ 'service_geoip' ] = function () {
89
  return Utilities\GeoIp::GetInstance();
90
  };
@@ -165,6 +168,13 @@ class Services {
165
  return self::getObj( __FUNCTION__ );
166
  }
167
 
 
 
 
 
 
 
 
168
  /**
169
  * @return Utilities\GeoIp
170
  */
85
  self::$oDic[ 'service_ip' ] = function () {
86
  return Utilities\IpUtils::GetInstance();
87
  };
88
+ self::$oDic[ 'service_encrypt' ] = function () {
89
+ return new Utilities\Encrypt\OpenSslEncrypt();
90
+ };
91
  self::$oDic[ 'service_geoip' ] = function () {
92
  return Utilities\GeoIp::GetInstance();
93
  };
168
  return self::getObj( __FUNCTION__ );
169
  }
170
 
171
+ /**
172
+ * @return Utilities\Encrypt\OpenSslEncrypt
173
+ */
174
+ static public function Encrypt() {
175
+ return self::getObj( __FUNCTION__ );
176
+ }
177
+
178
  /**
179
  * @return Utilities\GeoIp
180
  */
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Data.php CHANGED
@@ -344,20 +344,6 @@ class Data {
344
  Services::Response()->sendApache404();
345
  }
346
 
347
- /**
348
- * @param string $sStringContent
349
- * @param string $sFilename
350
- * @return bool
351
- */
352
- public function downloadStringAsFile( $sStringContent, $sFilename ) {
353
- header( "Content-type: application/octet-stream" );
354
- header( "Content-disposition: attachment; filename=".$sFilename );
355
- header( "Content-Transfer-Encoding: binary" );
356
- header( "Content-Length: ".strlen( $sStringContent ) );
357
- echo $sStringContent;
358
- die();
359
- }
360
-
361
  /**
362
  * @param $sKey
363
  * @param $mValue
@@ -514,4 +500,13 @@ class Data {
514
  && preg_match( "/^.{1,253}$/", $sDomainName ) //overall length check
515
  && preg_match( "/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $sDomainName ) );//length of each label
516
  }
 
 
 
 
 
 
 
 
 
517
  }
344
  Services::Response()->sendApache404();
345
  }
346
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
347
  /**
348
  * @param $sKey
349
  * @param $mValue
500
  && preg_match( "/^.{1,253}$/", $sDomainName ) //overall length check
501
  && preg_match( "/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $sDomainName ) );//length of each label
502
  }
503
+
504
+ /**
505
+ * @deprecated
506
+ * @param string $sStringContent
507
+ * @param string $sFilename
508
+ */
509
+ public function downloadStringAsFile( $sStringContent, $sFilename ) {
510
+ Services::Response()->downloadStringAsFile( $sStringContent, $sFilename );
511
+ }
512
  }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncrypt.php ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\Encrypt;
4
+
5
+ /**
6
+ * Class OpenSslEncrypt
7
+ * @package FernleafSystems\Wordpress\Services\Utilities\Encrypt
8
+ */
9
+ class OpenSslEncrypt {
10
+
11
+ /**
12
+ * @param array $aArgs
13
+ * @return array - keys are private & public as pem strings
14
+ * @throws \Exception
15
+ */
16
+ public function createNewPrivatePublicKeyPair( $aArgs = [] ) {
17
+ $rKey = openssl_pkey_new( $aArgs );
18
+ if ( empty( $rKey ) || !is_resource( $rKey ) ) {
19
+ throw new \Exception( 'Could not generate new private key' );
20
+ }
21
+ if ( !openssl_pkey_export( $rKey, $sPriv ) || empty( $sPriv ) ) {
22
+ throw new \Exception( 'Could not export new private key' );
23
+ }
24
+ $aPub = openssl_pkey_get_details( $rKey );
25
+ if ( empty( $aPub ) || empty( $aPub[ 'key' ] ) ) {
26
+ throw new \Exception( 'Could not generate public key from private' );
27
+ }
28
+ return [
29
+ 'private' => $sPriv,
30
+ 'public' => $aPub[ 'key' ],
31
+ ];
32
+ }
33
+
34
+ /**
35
+ * @param string $sKey
36
+ * @return string
37
+ * @throws \Exception
38
+ */
39
+ public function getPublicKeyFromPrivateKey( $sKey ) {
40
+ $rKey = openssl_pkey_get_private( $sKey );
41
+ if ( empty( $rKey ) || !is_resource( $rKey ) ) {
42
+ throw new \Exception( 'Could not build private key' );
43
+ }
44
+ $aPub = openssl_pkey_get_details( $rKey );
45
+ if ( empty( $aPub ) || empty( $aPub[ 'key' ] ) ) {
46
+ throw new \Exception( 'Could not generate public key from private' );
47
+ }
48
+ return $aPub[ 'key' ];
49
+ }
50
+
51
+ /**
52
+ * @param OpenSslEncryptVo $oVo
53
+ * @param string $sPrivateKey
54
+ * @return bool
55
+ */
56
+ public function openDataVo( $oVo, $sPrivateKey ) {
57
+ return $this->openData( $oVo->sealed_data, $oVo->sealed_password, $sPrivateKey );
58
+ }
59
+
60
+ /**
61
+ * @param string $sSealedData
62
+ * @param string $sSealedPassword
63
+ * @param string $sPrivateKey
64
+ * @return string|false
65
+ */
66
+ public function openData( $sSealedData, $sSealedPassword, $sPrivateKey ) {
67
+ $bResult = openssl_open( $sSealedData, $sOpenedData, $sSealedPassword, $sPrivateKey );
68
+ return $bResult ? $sOpenedData : false;
69
+ }
70
+
71
+ /**
72
+ * @param mixed $mDataToEncrypt
73
+ * @param string $sPublicKey
74
+ * @return OpenSslEncryptVo
75
+ */
76
+ public function sealData( $mDataToEncrypt, $sPublicKey ) {
77
+
78
+ $oVo = $this->getStandardEncryptResponse();
79
+
80
+ if ( empty( $mDataToEncrypt ) ) {
81
+ $oVo->success = false;
82
+ $oVo->message = 'Data to encrypt was empty';
83
+ return $oVo;
84
+ }
85
+ else if ( !$this->isSupportedOpenSslDataEncryption() ) {
86
+ $oVo->success = false;
87
+ $oVo->message = 'Does not support OpenSSL data encryption';
88
+ }
89
+ else {
90
+ $oVo->success = true;
91
+ }
92
+
93
+ // If at this stage we're not 'success' we return it.
94
+ if ( !$oVo->success ) {
95
+ return $oVo;
96
+ }
97
+
98
+ if ( !is_string( $mDataToEncrypt ) ) {
99
+ $mDataToEncrypt = json_encode( $mDataToEncrypt );
100
+ $oVo->json_encoded = true;
101
+ }
102
+ else {
103
+ $oVo->json_encoded = false;
104
+ }
105
+
106
+ $aPasswordKeys = array();
107
+ $nResult = openssl_seal( $mDataToEncrypt, $sEncryptedData, $aPasswordKeys, array( $sPublicKey ) );
108
+
109
+ $oVo->result = $nResult;
110
+ $oVo->success = is_int( $nResult ) && $nResult > 0 && !is_null( $sEncryptedData );
111
+ if ( $oVo->success ) {
112
+ $oVo->sealed_data = $sEncryptedData;
113
+ $oVo->sealed_password = $aPasswordKeys[ 0 ];
114
+ }
115
+
116
+ return $oVo;
117
+ }
118
+
119
+ /**
120
+ * @return bool
121
+ */
122
+ public function isSupportedOpenSsl() {
123
+ return extension_loaded( 'openssl' );
124
+ }
125
+
126
+ /**
127
+ * @return bool
128
+ */
129
+ public function isSupportedOpenSslSign() {
130
+ return function_exists( 'base64_decode' )
131
+ && extension_loaded( 'openssl' )
132
+ && function_exists( 'openssl_sign' )
133
+ && function_exists( 'openssl_verify' )
134
+ && defined( 'OPENSSL_ALGO_SHA1' );
135
+ }
136
+
137
+ /**
138
+ * @return bool
139
+ */
140
+ public function isSupportedOpenSslDataEncryption() {
141
+ $bSupported = $this->isSupportedOpenSsl();
142
+ $aFunc = [
143
+ 'openssl_seal',
144
+ 'openssl_open',
145
+ 'openssl_pkey_new',
146
+ 'openssl_pkey_export',
147
+ 'openssl_pkey_get_details',
148
+ 'openssl_pkey_get_private'
149
+ ];
150
+ foreach ( $aFunc as $sFunc ) {
151
+ $bSupported = $bSupported && function_exists( $sFunc );
152
+ }
153
+ return $bSupported;
154
+ }
155
+
156
+ /**
157
+ * @param string $sVerificationCode
158
+ * @param string $sSignature
159
+ * @param string $sPublicKey
160
+ * @return int 1: Success; 0: Failure; -1: Error; -2: Not supported
161
+ */
162
+ public function verifySslSignature( $sVerificationCode, $sSignature, $sPublicKey ) {
163
+ $nResult = -2;
164
+ if ( $this->isSupportedOpenSslSign() ) {
165
+ $nResult = openssl_verify( $sVerificationCode, $sSignature, $sPublicKey );
166
+ }
167
+ return $nResult;
168
+ }
169
+
170
+ /**
171
+ * @return OpenSslEncryptVo
172
+ */
173
+ protected function getStandardEncryptResponse() {
174
+ return new OpenSslEncryptVo();
175
+ }
176
+ }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Encrypt/OpenSslEncryptVo.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\Encrypt;
4
+
5
+ use FernleafSystems\Utilities\Data\Adapter\StdClassAdapter;
6
+
7
+ /**
8
+ * Class EncryptVo
9
+ * @package FernleafSystems\Wordpress\Services\Utilities\Encrypt
10
+ * @property bool $success
11
+ * @property int $result
12
+ * @property string $message
13
+ * @property bool $json_encoded
14
+ * @property string $sealed_data
15
+ * @property string $sealed_password
16
+ */
17
+ class OpenSslEncryptVo {
18
+
19
+ use StdClassAdapter {
20
+ __get as __adapterGet;
21
+ __set as __adapterSet;
22
+ }
23
+
24
+ /**
25
+ * @param string $sProperty
26
+ * @return mixed
27
+ */
28
+ public function __get( $sProperty ) {
29
+
30
+ $mVal = $this->__adapterGet( $sProperty );
31
+
32
+ switch ( $sProperty ) {
33
+
34
+ case 'sealed_data':
35
+ case 'sealed_password':
36
+ $mVal = base64_decode( $mVal );
37
+ break;
38
+
39
+ default:
40
+ break;
41
+ }
42
+
43
+ return $mVal;
44
+ }
45
+
46
+ /**
47
+ * @param string $sProperty
48
+ * @param mixed $mValue
49
+ * @return $this
50
+ */
51
+ public function __set( $sProperty, $mValue ) {
52
+
53
+ switch ( $sProperty ) {
54
+
55
+ case 'sealed_data':
56
+ case 'sealed_password':
57
+ $mValue = base64_encode( $mValue );
58
+ break;
59
+
60
+ default:
61
+ break;
62
+ }
63
+
64
+ return $this->__adapterSet( $sProperty, $mValue );
65
+ }
66
+ }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/File/ReadDataFromFileEncrypted.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\File;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+ use FernleafSystems\Wordpress\Services\Utilities\Encrypt\OpenSslEncryptVo;
7
+
8
+ /**
9
+ * Class ReadDataFromFileEncrypted
10
+ * @package FernleafSystems\Wordpress\Services\Utilities\File
11
+ */
12
+ class ReadDataFromFileEncrypted {
13
+
14
+ /**
15
+ * @param string $sPath
16
+ * @param string $sPrivateKey
17
+ * @return string
18
+ * @throws \Exception
19
+ */
20
+ public function run( $sPath, $sPrivateKey ) {
21
+ $oFs = Services::WpFs();
22
+ if ( !$oFs->exists( $sPath ) || !$oFs->isFile( $sPath ) ) {
23
+ throw new \Exception( 'File path does not exist: '.$sPath );
24
+ }
25
+ $sRawFile = $oFs->getFileContent( $sPath );
26
+ if ( empty( $sRawFile ) ) {
27
+ throw new \Exception( 'Could not read data from file: '.$sRawFile );
28
+ }
29
+ $aRawData = @json_decode( $sRawFile, true );
30
+ if ( empty( $aRawData ) || !is_array( $aRawData ) ) {
31
+ throw new \Exception( 'Parsing raw data from file failed' );
32
+ }
33
+
34
+ $oVo = ( new OpenSslEncryptVo() )->applyFromArray( $aRawData );
35
+
36
+ $sData = Services::Encrypt()->openData( $oVo->sealed_data, $oVo->sealed_password, $sPrivateKey );
37
+ if ( $sData === false ) {
38
+ throw new \Exception( 'Decrypting sealed data failed.' );
39
+ }
40
+ return $sData;
41
+ }
42
+ }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/File/TestFileWritable.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\File;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ /**
8
+ * Class TestFileWritable
9
+ * @package FernleafSystems\Wordpress\Services\Utilities\File
10
+ */
11
+ class TestFileWritable {
12
+
13
+ const TEST_STRING = '/** ODP TEST STRING %s */';
14
+
15
+ /**
16
+ * @param string $sPath
17
+ * @return bool
18
+ * @throws \Exception
19
+ */
20
+ public function run( $sPath ) {
21
+ if ( empty( $sPath ) ) {
22
+ throw new \Exception( 'File path is empty' );
23
+ }
24
+
25
+ $oFs = Services::WpFs();
26
+ if ( $oFs->isDir( $sPath ) ) {
27
+ throw new \Exception( 'Path is a directory and not file-writable' );
28
+ }
29
+
30
+ if ( $oFs->exists( $sPath ) ) {
31
+ $sContent = $oFs->getFileContent( $sPath );
32
+ if ( is_null( $sContent ) ) {
33
+ throw new \Exception( 'Could not read file contents' );
34
+ }
35
+ }
36
+ else {
37
+ $sContent = '';
38
+ }
39
+
40
+ { // Insert test string and write to file
41
+ $sTestString = sprintf( self::TEST_STRING, Services::WpGeneral()->getTimeStringForDisplay() );
42
+ $aLines = explode( "\n", $sContent );
43
+ $aLines[] = $sTestString;
44
+ $oFs->putFileContent( $sPath, implode( "\n", $aLines ) );
45
+ }
46
+
47
+ { // Re-read file contents and test for string
48
+ $sContent = $oFs->getFileContent( $sPath );
49
+ $bTestStringPresent = strpos( $sContent, $sTestString ) !== false;
50
+ }
51
+
52
+ { // Remove test string
53
+ if ( $bTestStringPresent ) {
54
+ $aLines = explode( "\n", $sContent );
55
+ array_pop( $aLines );
56
+ $oFs->putFileContent( $sPath, implode( "\n", $aLines ) );
57
+ }
58
+ }
59
+
60
+ return $bTestStringPresent;
61
+ }
62
+ }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/File/WriteDataToFileEncrypted.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\File;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ /**
8
+ * Class WriteDataToFileEncrypted
9
+ * @package FernleafSystems\Wordpress\Services\Utilities\File
10
+ */
11
+ class WriteDataToFileEncrypted {
12
+
13
+ /**
14
+ * @param string $sPath
15
+ * @param string $sData
16
+ * @param string $sPublicKey
17
+ * @param string $sPrivateKeyForVerify - verify writing successful if private key supplied
18
+ * @return bool
19
+ * @throws \Exception
20
+ */
21
+ public function run( $sPath, $sData, $sPublicKey, $sPrivateKeyForVerify = null ) {
22
+ $oEncrypt = Services::Encrypt();
23
+
24
+ $oEncrypted = $oEncrypt->sealData( $sData, $sPublicKey );
25
+ if ( !$oEncrypted->success ) {
26
+ throw new \Exception( 'Could not seal data with message: '.$oEncrypted->message );
27
+ }
28
+
29
+ $bSuccess = Services::WpFs()->putFileContent( $sPath, json_encode( $oEncrypted->getRawDataAsArray() ) );
30
+ if ( $bSuccess && !empty( $sPrivateKeyForVerify ) ) {
31
+ $bSuccess = ( new ReadDataFromFileEncrypted() )->run( $sPath, $sPrivateKeyForVerify ) === $sData;
32
+ }
33
+ return $bSuccess;
34
+ }
35
+ }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/HttpRequest.php CHANGED
@@ -86,7 +86,7 @@ class HttpRequest {
86
  $this->lastResponse = $this->send();
87
  }
88
  catch ( \Exception $oE ) {
89
- $this->lastError = new \WP_Error( $oE->getMessage() );
90
  }
91
  return $this;
92
  }
86
  $this->lastResponse = $this->send();
87
  }
88
  catch ( \Exception $oE ) {
89
+ $this->lastError = new \WP_Error( 'odp-http-error', $oE->getMessage() );
90
  }
91
  return $this;
92
  }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/IpUtils.php CHANGED
@@ -161,14 +161,17 @@ class IpUtils {
161
  /**
162
  * @param string $sIp
163
  * @return bool
 
164
  */
165
  public function isCloudFlareIp( $sIp ) {
166
- if ( $this->getIpVersion( $sIp ) == 4 ) {
167
- return $this->checkIp( $sIp, $this->getCloudFlareIpsV4() );
 
168
  }
169
- else {
170
- return $this->checkIp( $sIp, $this->getCloudFlareIpsV6() );
171
  }
 
172
  }
173
 
174
  /**
@@ -422,7 +425,8 @@ class IpUtils {
422
  */
423
  public function getServiceIps_StatusCake() {
424
  $aIps = array();
425
- $aData = @json_decode( Services::HttpRequest()->getContent( 'https://app.statuscake.com/Workfloor/Locations.php?format=json' ), true );
 
426
  if ( is_array( $aData ) ) {
427
  foreach ( $aData as $aItem ) {
428
  $aIps[] = $aItem[ 'ip' ];
161
  /**
162
  * @param string $sIp
163
  * @return bool
164
+ * @throws \Exception
165
  */
166
  public function isCloudFlareIp( $sIp ) {
167
+ try {
168
+ $aIps = ( $this->getIpVersion( $sIp ) == 4 ) ? $this->getCloudFlareIpsV4() : $this->getCloudFlareIpsV6();
169
+ $bIs = $this->checkIp( $sIp, $aIps );
170
  }
171
+ catch ( \Exception $oE ) {
172
+ $bIs = false;
173
  }
174
+ return $bIs;
175
  }
176
 
177
  /**
425
  */
426
  public function getServiceIps_StatusCake() {
427
  $aIps = array();
428
+ $aData = @json_decode( Services::HttpRequest()
429
+ ->getContent( 'https://app.statuscake.com/Workfloor/Locations.php?format=json' ), true );
430
  if ( is_array( $aData ) ) {
431
  foreach ( $aData as $aItem ) {
432
  $aIps[] = $aItem[ 'ip' ];
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/Net/VisitorIpDetection.php ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace FernleafSystems\Wordpress\Services\Utilities\Net;
4
+
5
+ use FernleafSystems\Wordpress\Services\Services;
6
+
7
+ /**
8
+ * Class VisitorIpDetection
9
+ * @package FernleafSystems\Wordpress\Services\Utilities\Net
10
+ */
11
+ class VisitorIpDetection {
12
+
13
+ const DEFAULT_SOURCE = 'REMOTE_ADDR';
14
+
15
+ /**
16
+ * @var string[]
17
+ */
18
+ private $aPotentialHostIps;
19
+
20
+ /**
21
+ * @var string
22
+ */
23
+ private $sLastSuccessfulSource;
24
+
25
+ /**
26
+ * @var string
27
+ */
28
+ private $sPreferredSource;
29
+
30
+ /**
31
+ * @return string
32
+ */
33
+ public function detect() {
34
+ return $this->runNormalDetection();
35
+ }
36
+
37
+ /**
38
+ * Progressively removes Host IPs from the list so that these don't interfere with detection.
39
+ * @return string
40
+ */
41
+ public function alternativeDetect() {
42
+ do {
43
+ $sIp = $this->runNormalDetection();
44
+ if ( !empty( $sIp ) ) {
45
+ break;
46
+ }
47
+
48
+ // Progressively remove a Host IP until there's none left.
49
+ $aHostIps = $this->getPotentialHostIps();
50
+ if ( empty( $aHostIps ) ) {
51
+ break;
52
+ }
53
+ array_shift( $aHostIps );
54
+ $this->setPotentialHostIps( $aHostIps );
55
+
56
+ } while ( empty( $sIp ) );
57
+
58
+ return $sIp;
59
+ }
60
+
61
+ /**
62
+ * @return string
63
+ */
64
+ private function runNormalDetection() {
65
+ $sSource = '';
66
+ $aIps = $this->detectAndFilterFromSource( $this->getPreferredSource() );
67
+
68
+ if ( empty( $aIps ) ) { // Couldn't detect IP from preferred source.
69
+
70
+ foreach ( $this->getIpSourceOptions() as $sMaybeSource ) {
71
+ $aIps = $this->detectAndFilterFromSource( $sMaybeSource );
72
+ if ( !empty( $aIps ) ) {
73
+ $sSource = $sMaybeSource;
74
+ break;
75
+ }
76
+ }
77
+ }
78
+ else {
79
+ $sSource = $this->getPreferredSource();
80
+ }
81
+
82
+ $this->sLastSuccessfulSource = $sSource;
83
+ return empty( $aIps ) ? '' : array_shift( $aIps );
84
+ }
85
+
86
+ /**
87
+ * @param string $sSource
88
+ * @return string[]
89
+ */
90
+ protected function detectAndFilterFromSource( $sSource ) {
91
+ return $this->filterIpsByViable( $this->getIpsFromSource( $sSource ) );
92
+ }
93
+
94
+ /**
95
+ * @param string[] $aIps
96
+ * @return string[]
97
+ */
98
+ protected function filterIpsByViable( $aIps ) {
99
+ return array_values( array_filter(
100
+ $aIps,
101
+ function ( $sIp ) {
102
+ $oIP = Services::IP();
103
+ return ( $oIP->isValidIp_PublicRemote( $sIp )
104
+ && !$oIP->checkIp( $sIp, $this->getPotentialHostIps() )
105
+ && !$oIP->isCloudFlareIp( $sIp )
106
+ );
107
+ }
108
+ ) );
109
+ }
110
+
111
+ /**
112
+ * @param string $sSource
113
+ * @return string[]
114
+ */
115
+ protected function getIpsFromSource( $sSource ) {
116
+ $sRawSource = (string)Services::Request()->server( $sSource );
117
+ $aRaw = empty( $sRawSource ) ? [] : explode( ',', $sRawSource );
118
+ return array_filter(
119
+ array_map( 'trim', $aRaw ),
120
+ function ( $sIp ) {
121
+ return filter_var( $sIp, FILTER_VALIDATE_IP ) !== false;
122
+ }
123
+ );
124
+ }
125
+
126
+ /**
127
+ * @return string[]
128
+ */
129
+ public function getPotentialHostIps() {
130
+ return is_array( $this->aPotentialHostIps ) ? $this->aPotentialHostIps : [];
131
+ }
132
+
133
+ /**
134
+ * @return string
135
+ */
136
+ public function getLastSuccessfulSource() {
137
+ return (string)$this->sLastSuccessfulSource;
138
+ }
139
+
140
+ /**
141
+ * @return string
142
+ */
143
+ public function getPreferredSource() {
144
+ return empty( $this->sPreferredSource ) ? self::DEFAULT_SOURCE : $this->sPreferredSource;
145
+ }
146
+
147
+ /**
148
+ * @param string[] $aPotentialHostIps
149
+ * @return $this
150
+ */
151
+ public function setPotentialHostIps( $aPotentialHostIps ) {
152
+ $this->aPotentialHostIps = $aPotentialHostIps;
153
+ return $this;
154
+ }
155
+
156
+ /**
157
+ * @param string $sDefaultSource
158
+ * @return $this
159
+ */
160
+ public function setPreferredSource( $sDefaultSource ) {
161
+ $this->sPreferredSource = $sDefaultSource;
162
+ return $this;
163
+ }
164
+
165
+ /**
166
+ * @return string[]
167
+ */
168
+ private function getIpSourceOptions() {
169
+ return array(
170
+ 'REMOTE_ADDR',
171
+ 'HTTP_CF_CONNECTING_IP',
172
+ 'HTTP_X_FORWARDED_FOR',
173
+ 'HTTP_X_FORWARDED',
174
+ 'HTTP_X_REAL_IP',
175
+ 'HTTP_X_SUCURI_CLIENTIP',
176
+ 'HTTP_INCAP_CLIENT_IP',
177
+ 'HTTP_X_SP_FORWARDED_IP',
178
+ 'HTTP_FORWARDED',
179
+ 'HTTP_CLIENT_IP'
180
+ );
181
+ }
182
+ }
src/lib/vendor/fernleafsystems/wordpress-services/src/Utilities/ServiceProviders.php CHANGED
@@ -77,23 +77,23 @@ class ServiceProviders {
77
 
78
  /**
79
  * @param bool $bFlat
80
- * @return array[]|string[]
81
  */
82
  public function getIps_iControlWP( $bFlat = false ) {
83
  $oWp = Services::WpGeneral();
84
 
85
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_icontrolwp' );
86
  $aIps = $oWp->getTransient( $sStoreKey );
87
- if ( empty( $aIps ) ) {
88
- $aIps = $this->downloadServiceIps_iControlWP();
 
89
  $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*2 );
90
  }
91
-
92
  return $bFlat ? array_merge( $aIps[ 4 ], $aIps[ 6 ] ) : $aIps;
93
  }
94
 
95
  /**
96
- * @return array[]
97
  */
98
  public function getIps_ManageWp() {
99
  $oWp = Services::WpGeneral();
@@ -101,16 +101,17 @@ class ServiceProviders {
101
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_managewp' );
102
  $aIps = $oWp->getTransient( $sStoreKey );
103
  if ( empty( $aIps ) ) {
104
- $aIps = $this->downloadServiceIps_ManageWp();
105
  $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
106
  }
107
  return $aIps;
108
  }
109
 
110
  /**
111
- * @return string[][]
 
112
  */
113
- public function getIps_Pingdom() {
114
  $oWp = Services::WpGeneral();
115
 
116
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_pingdom' );
@@ -122,7 +123,7 @@ class ServiceProviders {
122
  );
123
  $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
124
  }
125
- return $aIps;
126
  }
127
 
128
  /**
@@ -133,17 +134,27 @@ class ServiceProviders {
133
 
134
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_statuscake' );
135
  $aIps = $oWp->getTransient( $sStoreKey );
136
- if ( empty( $aIps ) || !is_array( $aIps ) ) {
137
- $aIps = $this->downloadServiceIps_StatusCake();
 
 
 
 
 
 
 
 
 
138
  $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
139
  }
140
  return $aIps;
141
  }
142
 
143
  /**
144
- * @return array[]
 
145
  */
146
- public function getIps_UptimeRobot() {
147
  $oWp = Services::WpGeneral();
148
 
149
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_uptimerobot' );
@@ -155,7 +166,7 @@ class ServiceProviders {
155
  );
156
  $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
157
  }
158
- return $aIps;
159
  }
160
 
161
  /**
@@ -169,7 +180,7 @@ class ServiceProviders {
169
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_applebot' );
170
  $aIps = $oWp->getTransient( $sStoreKey );
171
  if ( !is_array( $aIps ) ) {
172
- $aIps = array();
173
  }
174
 
175
  if ( !in_array( $sIp, $aIps ) && $this->verifyIp_AppleBot( $sIp, $sUserAgent ) ) {
@@ -191,7 +202,7 @@ class ServiceProviders {
191
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_baidubot' );
192
  $aIps = $oWp->getTransient( $sStoreKey );
193
  if ( !is_array( $aIps ) ) {
194
- $aIps = array();
195
  }
196
 
197
  if ( !in_array( $sIp, $aIps ) && $this->verifyIp_BaiduBot( $sIp, $sUserAgent ) ) {
@@ -213,7 +224,7 @@ class ServiceProviders {
213
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_bingbot' );
214
  $aIps = $oWp->getTransient( $sStoreKey );
215
  if ( !is_array( $aIps ) ) {
216
- $aIps = array();
217
  }
218
 
219
  if ( !in_array( $sIp, $aIps ) && $this->verifyIp_BingBot( $sIp, $sUserAgent ) ) {
@@ -232,11 +243,9 @@ class ServiceProviders {
232
  $bIs = false;
233
  try {
234
  $oIp = Services::IP();
235
- if ( $oIp->getIpVersion( $sIp ) == 4 ) {
236
- $bIs = $oIp->checkIp( $sIp, $this->getIps_CloudFlareV4() );
237
- }
238
- else {
239
- $bIs = $oIp->checkIp( $sIp, $this->getIps_CloudFlareV6() );
240
  }
241
  }
242
  catch ( \Exception $oE ) {
@@ -284,7 +293,7 @@ class ServiceProviders {
284
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_googlebot' );
285
  $aIps = $oWp->getTransient( $sStoreKey );
286
  if ( !is_array( $aIps ) ) {
287
- $aIps = array();
288
  }
289
 
290
  if ( !in_array( $sIp, $aIps ) && $this->verifyIp_GoogleBot( $sIp, $sUserAgent ) ) {
@@ -301,12 +310,8 @@ class ServiceProviders {
301
  * @return bool
302
  */
303
  public function isIp_Statuscake( $sIp, $sAgent ) {
304
- $bIsIp = false;
305
- if ( stripos( $sAgent, 'StatusCake' ) !== false ) {
306
- $aIps = $this->getIps_Statuscake();
307
- $bIsIp = in_array( $sIp, $aIps );
308
- }
309
- return $bIsIp;
310
  }
311
 
312
  /**
@@ -315,12 +320,8 @@ class ServiceProviders {
315
  * @return bool
316
  */
317
  public function isIp_Pingdom( $sIp, $sAgent ) {
318
- $bIsIp = false;
319
- if ( stripos( $sAgent, 'pingdom.com' ) !== false ) {
320
- $aIps = $this->getIps_Pingdom();
321
- $bIsIp = in_array( $sIp, $aIps[ Services::IP()->getIpVersion( $sIp ) ] );
322
- }
323
- return $bIsIp;
324
  }
325
 
326
  /**
@@ -329,12 +330,8 @@ class ServiceProviders {
329
  * @return bool
330
  */
331
  public function isIp_UptimeRobot( $sIp, $sAgent ) {
332
- $bIsIp = false;
333
- if ( stripos( $sAgent, 'UptimeRobot' ) !== false ) {
334
- $aIps = $this->getIps_UptimeRobot();
335
- $bIsIp = in_array( $sIp, $aIps[ Services::IP()->getIpVersion( $sIp ) ] );
336
- }
337
- return $bIsIp;
338
  }
339
 
340
  /**
@@ -349,7 +346,7 @@ class ServiceProviders {
349
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_yandexbot' );
350
  $aIps = $oWp->getTransient( $sStoreKey );
351
  if ( !is_array( $aIps ) ) {
352
- $aIps = array();
353
  }
354
 
355
  if ( !in_array( $sIp, $aIps ) && $this->verifyIp_YandexBot( $sIp, $sUserAgent ) ) {
@@ -372,7 +369,7 @@ class ServiceProviders {
372
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_yahoobot' );
373
  $aIps = $oWp->getTransient( $sStoreKey );
374
  if ( !is_array( $aIps ) ) {
375
- $aIps = array();
376
  }
377
 
378
  if ( !in_array( $sIp, $aIps ) && $this->verifyIp_YahooBot( $sIp, $sUserAgent ) ) {
@@ -460,7 +457,7 @@ class ServiceProviders {
460
  if ( !$bCheckIpHost ) {
461
  $aBotUserAgents = array_map(
462
  function ( $sAgent ) {
463
- preg_quote( $sAgent, '#' );
464
  },
465
  $aBotUserAgents
466
  );
@@ -484,21 +481,6 @@ class ServiceProviders {
484
  return $this->downloadServiceIps_Standard( self::URL_IPS_CLOUDFLARE, $sIpVersion );
485
  }
486
 
487
- /**
488
- * @return string[]
489
- */
490
- private function downloadServiceIps_ManageWp() {
491
- return $this->downloadServiceIps_Standard( self::URL_IPS_MANAGEWP );
492
- }
493
-
494
- /**
495
- * @return array[]
496
- */
497
- private function downloadServiceIps_iControlWP() {
498
- $aIps = @json_decode( Services::HttpRequest()->getContent( self::URL_IPS_ICONTROLWP ), true );
499
- return is_array( $aIps ) ? $aIps : [ 4 => [], 6 => [] ];
500
- }
501
-
502
  /**
503
  * @param int $sIpVersion
504
  * @return string[]
@@ -507,22 +489,6 @@ class ServiceProviders {
507
  return $this->downloadServiceIps_Standard( self::URL_IPS_PINGDOM, $sIpVersion );
508
  }
509
 
510
- /**
511
- * @return string[]
512
- */
513
- private function downloadServiceIps_StatusCake() {
514
- $aIps = array();
515
- $aData = @json_decode( Services::HttpRequest()->getContent( self::URL_IPS_STATUSCAKE ), true );
516
- if ( is_array( $aData ) ) {
517
- foreach ( $aData as $aItem ) {
518
- if ( !empty( $aItem[ 'ip' ] ) ) {
519
- $aIps[] = $aItem[ 'ip' ];
520
- }
521
- }
522
- }
523
- return $aIps;
524
- }
525
-
526
  /**
527
  * @param int $sIpVersion
528
  * @return string[]
@@ -544,8 +510,8 @@ class ServiceProviders {
544
  $sSourceUrl = Services::HttpRequest()->getContent( sprintf( $sSourceUrl, $sIpVersion ) );
545
  }
546
  $sRaw = Services::HttpRequest()->getContent( $sSourceUrl );
547
- $aIps = empty( $sRaw ) ? array() : explode( "\n", $sRaw );
548
- return array_filter( array_map( 'trim', $aIps ) );
549
  }
550
 
551
  /**
77
 
78
  /**
79
  * @param bool $bFlat
80
+ * @return string[][]|string[]
81
  */
82
  public function getIps_iControlWP( $bFlat = false ) {
83
  $oWp = Services::WpGeneral();
84
 
85
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_icontrolwp' );
86
  $aIps = $oWp->getTransient( $sStoreKey );
87
+ if ( !is_array( $aIps ) ) {
88
+ $aIps = @json_decode( Services::HttpRequest()->getContent( self::URL_IPS_ICONTROLWP ), true );
89
+ $aIps = is_array( $aIps ) ? $aIps : [ 4 => [], 6 => [] ];
90
  $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*2 );
91
  }
 
92
  return $bFlat ? array_merge( $aIps[ 4 ], $aIps[ 6 ] ) : $aIps;
93
  }
94
 
95
  /**
96
+ * @return string[]
97
  */
98
  public function getIps_ManageWp() {
99
  $oWp = Services::WpGeneral();
101
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_managewp' );
102
  $aIps = $oWp->getTransient( $sStoreKey );
103
  if ( empty( $aIps ) ) {
104
+ $aIps = $this->downloadServiceIps_Standard( self::URL_IPS_MANAGEWP );
105
  $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
106
  }
107
  return $aIps;
108
  }
109
 
110
  /**
111
+ * @param bool $bFlat
112
+ * @return string[][]|string[]
113
  */
114
+ public function getIps_Pingdom( $bFlat = false ) {
115
  $oWp = Services::WpGeneral();
116
 
117
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_pingdom' );
123
  );
124
  $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
125
  }
126
+ return $bFlat ? array_merge( $aIps[ 4 ], $aIps[ 6 ] ) : $aIps;
127
  }
128
 
129
  /**
134
 
135
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_statuscake' );
136
  $aIps = $oWp->getTransient( $sStoreKey );
137
+ if ( !is_array( $aIps ) ) {
138
+ $aIps = [];
139
+ $aData = @json_decode( Services::HttpRequest()->getContent( self::URL_IPS_STATUSCAKE ), true );
140
+ if ( is_array( $aData ) ) {
141
+ $aIps = array_values( array_filter( array_map(
142
+ function ( $aItem ) {
143
+ return empty( $aItem[ 'ip' ] ) ? null : $aItem[ 'ip' ];
144
+ },
145
+ $aData
146
+ ) ) );
147
+ }
148
  $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
149
  }
150
  return $aIps;
151
  }
152
 
153
  /**
154
+ * @param bool $bFlat - false for segregated IPv4 and IPv6
155
+ * @return string[][]|string[]
156
  */
157
+ public function getIps_UptimeRobot( $bFlat = false ) {
158
  $oWp = Services::WpGeneral();
159
 
160
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_uptimerobot' );
166
  );
167
  $oWp->setTransient( $sStoreKey, $aIps, WEEK_IN_SECONDS*4 );
168
  }
169
+ return $bFlat ? array_merge( $aIps[ 4 ], $aIps[ 6 ] ) : $aIps;
170
  }
171
 
172
  /**
180
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_applebot' );
181
  $aIps = $oWp->getTransient( $sStoreKey );
182
  if ( !is_array( $aIps ) ) {
183
+ $aIps = [];
184
  }
185
 
186
  if ( !in_array( $sIp, $aIps ) && $this->verifyIp_AppleBot( $sIp, $sUserAgent ) ) {
202
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_baidubot' );
203
  $aIps = $oWp->getTransient( $sStoreKey );
204
  if ( !is_array( $aIps ) ) {
205
+ $aIps = [];
206
  }
207
 
208
  if ( !in_array( $sIp, $aIps ) && $this->verifyIp_BaiduBot( $sIp, $sUserAgent ) ) {
224
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_bingbot' );
225
  $aIps = $oWp->getTransient( $sStoreKey );
226
  if ( !is_array( $aIps ) ) {
227
+ $aIps = [];
228
  }
229
 
230
  if ( !in_array( $sIp, $aIps ) && $this->verifyIp_BingBot( $sIp, $sUserAgent ) ) {
243
  $bIs = false;
244
  try {
245
  $oIp = Services::IP();
246
+ $nVersion = $oIp->getIpVersion( $sIp );
247
+ if ( in_array( $nVersion, [ 4, 6 ] ) ) {
248
+ $bIs = $oIp->checkIp( $sIp, $this->getIps_CloudFlare()[ $nVersion ] );
 
 
249
  }
250
  }
251
  catch ( \Exception $oE ) {
293
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_googlebot' );
294
  $aIps = $oWp->getTransient( $sStoreKey );
295
  if ( !is_array( $aIps ) ) {
296
+ $aIps = [];
297
  }
298
 
299
  if ( !in_array( $sIp, $aIps ) && $this->verifyIp_GoogleBot( $sIp, $sUserAgent ) ) {
310
  * @return bool
311
  */
312
  public function isIp_Statuscake( $sIp, $sAgent ) {
313
+ return ( stripos( $sAgent, 'StatusCake' ) !== false )
314
+ && in_array( $sIp, $this->getIps_Statuscake() );
 
 
 
 
315
  }
316
 
317
  /**
320
  * @return bool
321
  */
322
  public function isIp_Pingdom( $sIp, $sAgent ) {
323
+ return ( stripos( $sAgent, 'pingdom.com' ) !== false )
324
+ && in_array( $sIp, $this->getIps_Pingdom( true ) );
 
 
 
 
325
  }
326
 
327
  /**
330
  * @return bool
331
  */
332
  public function isIp_UptimeRobot( $sIp, $sAgent ) {
333
+ return ( stripos( $sAgent, 'UptimeRobot' ) !== false )
334
+ && in_array( $sIp, $this->getIps_UptimeRobot( true ) );
 
 
 
 
335
  }
336
 
337
  /**
346
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_yandexbot' );
347
  $aIps = $oWp->getTransient( $sStoreKey );
348
  if ( !is_array( $aIps ) ) {
349
+ $aIps = [];
350
  }
351
 
352
  if ( !in_array( $sIp, $aIps ) && $this->verifyIp_YandexBot( $sIp, $sUserAgent ) ) {
369
  $sStoreKey = $this->getPrefixedStoreKey( 'serviceips_yahoobot' );
370
  $aIps = $oWp->getTransient( $sStoreKey );
371
  if ( !is_array( $aIps ) ) {
372
+ $aIps = [];
373
  }
374
 
375
  if ( !in_array( $sIp, $aIps ) && $this->verifyIp_YahooBot( $sIp, $sUserAgent ) ) {
457
  if ( !$bCheckIpHost ) {
458
  $aBotUserAgents = array_map(
459
  function ( $sAgent ) {
460
+ return preg_quote( $sAgent, '#' );
461
  },
462
  $aBotUserAgents
463
  );
481
  return $this->downloadServiceIps_Standard( self::URL_IPS_CLOUDFLARE, $sIpVersion );
482
  }
483
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
484
  /**
485
  * @param int $sIpVersion
486
  * @return string[]
489
  return $this->downloadServiceIps_Standard( self::URL_IPS_PINGDOM, $sIpVersion );
490
  }
491
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
492
  /**
493
  * @param int $sIpVersion
494
  * @return string[]
510
  $sSourceUrl = Services::HttpRequest()->getContent( sprintf( $sSourceUrl, $sIpVersion ) );
511
  }
512
  $sRaw = Services::HttpRequest()->getContent( $sSourceUrl );
513
+ $aIps = empty( $sRaw ) ? [] : explode( "\n", $sRaw );
514
+ return array_values( array_filter( array_map( 'trim', $aIps ) ) );
515
  }
516
 
517
  /**
src/lib/vendor/twig/twig/lib/Twig/Autoloader.php CHANGED
@@ -43,7 +43,9 @@ class Twig_Autoloader
43
  return;
44
  }
45
 
46
- if (is_file($file = dirname(__FILE__).'/../'.str_replace(['_', "\0"], ['/', ''], $class).'.php')) {
 
 
47
  require $file;
48
  }
49
  }
43
  return;
44
  }
45
 
46
+ if (is_file($file = __DIR__.'/../'.str_replace(['_', "\0"], ['/', ''], $class).'.php')) {
47
+ require $file;
48
+ } elseif (is_file($file = __DIR__.'/../../src/'.str_replace(['Twig\\', '\\', "\0"], ['', '/', ''], $class).'.php')) {
49
  require $file;
50
  }
51
  }
src/lib/vendor/twig/twig/lib/Twig/BaseNodeVisitor.php CHANGED
@@ -1,54 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Twig_BaseNodeVisitor can be used to make node visitors compatible with Twig 1.x and 2.x.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- abstract class Twig_BaseNodeVisitor implements Twig_NodeVisitorInterface
18
- {
19
- final public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
20
- {
21
- if (!$node instanceof Twig_Node) {
22
- throw new LogicException('Twig_BaseNodeVisitor only supports Twig_Node instances.');
23
- }
24
-
25
- return $this->doEnterNode($node, $env);
26
- }
27
 
28
- final public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
 
29
  {
30
- if (!$node instanceof Twig_Node) {
31
- throw new LogicException('Twig_BaseNodeVisitor only supports Twig_Node instances.');
32
- }
33
-
34
- return $this->doLeaveNode($node, $env);
35
  }
36
-
37
- /**
38
- * Called before child nodes are visited.
39
- *
40
- * @return Twig_Node The modified node
41
- */
42
- abstract protected function doEnterNode(Twig_Node $node, Twig_Environment $env);
43
-
44
- /**
45
- * Called after child nodes are visited.
46
- *
47
- * @return Twig_Node|false The modified node or false if the node must be removed
48
- */
49
- abstract protected function doLeaveNode(Twig_Node $node, Twig_Environment $env);
50
  }
51
-
52
- class_alias('Twig_BaseNodeVisitor', 'Twig\NodeVisitor\AbstractNodeVisitor', false);
53
- class_exists('Twig_Environment');
54
- class_exists('Twig_Node');
1
  <?php
2
 
3
+ use Twig\NodeVisitor\AbstractNodeVisitor;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\NodeVisitor\AbstractNodeVisitor');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_BaseNodeVisitor extends AbstractNodeVisitor
9
  {
 
 
 
 
 
10
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  }
 
 
 
 
src/lib/vendor/twig/twig/lib/Twig/Cache/Filesystem.php CHANGED
@@ -1,91 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Implements a cache on the filesystem.
14
- *
15
- * @author Andrew Tch <andrew@noop.lv>
16
- */
17
- class Twig_Cache_Filesystem implements Twig_CacheInterface
18
- {
19
- const FORCE_BYTECODE_INVALIDATION = 1;
20
 
21
- private $directory;
22
- private $options;
23
-
24
- /**
25
- * @param $directory string The root cache directory
26
- * @param $options int A set of options
27
- */
28
- public function __construct($directory, $options = 0)
29
- {
30
- $this->directory = rtrim($directory, '\/').'/';
31
- $this->options = $options;
32
- }
33
-
34
- public function generateKey($name, $className)
35
- {
36
- $hash = hash('sha256', $className);
37
-
38
- return $this->directory.$hash[0].$hash[1].'/'.$hash.'.php';
39
- }
40
-
41
- public function load($key)
42
- {
43
- if (file_exists($key)) {
44
- @include_once $key;
45
- }
46
- }
47
-
48
- public function write($key, $content)
49
- {
50
- $dir = dirname($key);
51
- if (!is_dir($dir)) {
52
- if (false === @mkdir($dir, 0777, true)) {
53
- clearstatcache(true, $dir);
54
- if (!is_dir($dir)) {
55
- throw new RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir));
56
- }
57
- }
58
- } elseif (!is_writable($dir)) {
59
- throw new RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir));
60
- }
61
-
62
- $tmpFile = tempnam($dir, basename($key));
63
- if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $key)) {
64
- @chmod($key, 0666 & ~umask());
65
-
66
- if (self::FORCE_BYTECODE_INVALIDATION == ($this->options & self::FORCE_BYTECODE_INVALIDATION)) {
67
- // Compile cached file into bytecode cache
68
- if (function_exists('opcache_invalidate')) {
69
- opcache_invalidate($key, true);
70
- } elseif (function_exists('apc_compile_file')) {
71
- apc_compile_file($key);
72
- }
73
- }
74
-
75
- return;
76
- }
77
-
78
- throw new RuntimeException(sprintf('Failed to write cache file "%s".', $key));
79
- }
80
-
81
- public function getTimestamp($key)
82
  {
83
- if (!file_exists($key)) {
84
- return 0;
85
- }
86
-
87
- return (int) @filemtime($key);
88
  }
89
  }
90
-
91
- class_alias('Twig_Cache_Filesystem', 'Twig\Cache\FilesystemCache', false);
1
  <?php
2
 
3
+ use Twig\Cache\FilesystemCache;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Cache\FilesystemCache');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Cache_Filesystem extends FilesystemCache
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Cache/Null.php CHANGED
@@ -1,40 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Implements a no-cache strategy.
14
- *
15
- * @final
16
- *
17
- * @author Fabien Potencier <fabien@symfony.com>
18
- */
19
- class Twig_Cache_Null implements Twig_CacheInterface
20
- {
21
- public function generateKey($name, $className)
22
- {
23
- return '';
24
- }
25
-
26
- public function write($key, $content)
27
- {
28
- }
29
 
30
- public function load($key)
 
31
  {
32
  }
33
-
34
- public function getTimestamp($key)
35
- {
36
- return 0;
37
- }
38
  }
39
-
40
- class_alias('Twig_Cache_Null', 'Twig\Cache\NullCache', false);
1
  <?php
2
 
3
+ use Twig\Cache\NullCache;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Cache\NullCache');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Cache_Null extends NullCache
9
  {
10
  }
 
 
 
 
 
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/CacheInterface.php CHANGED
@@ -1,58 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Interface implemented by cache classes.
14
- *
15
- * It is highly recommended to always store templates on the filesystem to
16
- * benefit from the PHP opcode cache. This interface is mostly useful if you
17
- * need to implement a custom strategy for storing templates on the filesystem.
18
- *
19
- * @author Andrew Tch <andrew@noop.lv>
20
- */
21
- interface Twig_CacheInterface
22
- {
23
- /**
24
- * Generates a cache key for the given template class name.
25
- *
26
- * @param string $name The template name
27
- * @param string $className The template class name
28
- *
29
- * @return string
30
- */
31
- public function generateKey($name, $className);
32
 
33
- /**
34
- * Writes the compiled template to cache.
35
- *
36
- * @param string $key The cache key
37
- * @param string $content The template representation as a PHP class
38
- */
39
- public function write($key, $content);
40
-
41
- /**
42
- * Loads a template from the cache.
43
- *
44
- * @param string $key The cache key
45
- */
46
- public function load($key);
47
-
48
- /**
49
- * Returns the modification timestamp of a key.
50
- *
51
- * @param string $key The cache key
52
- *
53
- * @return int
54
- */
55
- public function getTimestamp($key);
56
  }
57
-
58
- class_alias('Twig_CacheInterface', 'Twig\Cache\CacheInterface', false);
1
  <?php
2
 
3
+ use Twig\Cache\CacheInterface;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Cache\CacheInterface');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_CacheInterface extends CacheInterface
9
+ {
10
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Compiler.php CHANGED
@@ -1,286 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Compiles a node to PHP code.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- class Twig_Compiler implements Twig_CompilerInterface
19
- {
20
- protected $lastLine;
21
- protected $source;
22
- protected $indentation;
23
- protected $env;
24
- protected $debugInfo = [];
25
- protected $sourceOffset;
26
- protected $sourceLine;
27
- protected $filename;
28
- private $varNameSalt = 0;
29
 
30
- public function __construct(Twig_Environment $env)
 
31
  {
32
- $this->env = $env;
33
- }
34
-
35
- /**
36
- * @deprecated since 1.25 (to be removed in 2.0)
37
- */
38
- public function getFilename()
39
- {
40
- @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED);
41
-
42
- return $this->filename;
43
- }
44
-
45
- /**
46
- * Returns the environment instance related to this compiler.
47
- *
48
- * @return Twig_Environment
49
- */
50
- public function getEnvironment()
51
- {
52
- return $this->env;
53
- }
54
-
55
- /**
56
- * Gets the current PHP code after compilation.
57
- *
58
- * @return string The PHP code
59
- */
60
- public function getSource()
61
- {
62
- return $this->source;
63
- }
64
-
65
- /**
66
- * Compiles a node.
67
- *
68
- * @param Twig_NodeInterface $node The node to compile
69
- * @param int $indentation The current indentation
70
- *
71
- * @return $this
72
- */
73
- public function compile(Twig_NodeInterface $node, $indentation = 0)
74
- {
75
- $this->lastLine = null;
76
- $this->source = '';
77
- $this->debugInfo = [];
78
- $this->sourceOffset = 0;
79
- // source code starts at 1 (as we then increment it when we encounter new lines)
80
- $this->sourceLine = 1;
81
- $this->indentation = $indentation;
82
- $this->varNameSalt = 0;
83
-
84
- if ($node instanceof Twig_Node_Module) {
85
- // to be removed in 2.0
86
- $this->filename = $node->getTemplateName();
87
- }
88
-
89
- $node->compile($this);
90
-
91
- return $this;
92
- }
93
-
94
- public function subcompile(Twig_NodeInterface $node, $raw = true)
95
- {
96
- if (false === $raw) {
97
- $this->source .= str_repeat(' ', $this->indentation * 4);
98
- }
99
-
100
- $node->compile($this);
101
-
102
- return $this;
103
- }
104
-
105
- /**
106
- * Adds a raw string to the compiled code.
107
- *
108
- * @param string $string The string
109
- *
110
- * @return $this
111
- */
112
- public function raw($string)
113
- {
114
- $this->source .= $string;
115
-
116
- return $this;
117
- }
118
-
119
- /**
120
- * Writes a string to the compiled code by adding indentation.
121
- *
122
- * @return $this
123
- */
124
- public function write()
125
- {
126
- $strings = func_get_args();
127
- foreach ($strings as $string) {
128
- $this->source .= str_repeat(' ', $this->indentation * 4).$string;
129
- }
130
-
131
- return $this;
132
- }
133
-
134
- /**
135
- * Appends an indentation to the current PHP code after compilation.
136
- *
137
- * @return $this
138
- *
139
- * @deprecated since 1.27 (to be removed in 2.0).
140
- */
141
- public function addIndentation()
142
- {
143
- @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use write(\'\') instead.', E_USER_DEPRECATED);
144
-
145
- $this->source .= str_repeat(' ', $this->indentation * 4);
146
-
147
- return $this;
148
- }
149
-
150
- /**
151
- * Adds a quoted string to the compiled code.
152
- *
153
- * @param string $value The string
154
- *
155
- * @return $this
156
- */
157
- public function string($value)
158
- {
159
- $this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\"));
160
-
161
- return $this;
162
- }
163
-
164
- /**
165
- * Returns a PHP representation of a given value.
166
- *
167
- * @param mixed $value The value to convert
168
- *
169
- * @return $this
170
- */
171
- public function repr($value)
172
- {
173
- if (is_int($value) || is_float($value)) {
174
- if (false !== $locale = setlocale(LC_NUMERIC, '0')) {
175
- setlocale(LC_NUMERIC, 'C');
176
- }
177
-
178
- $this->raw(var_export($value, true));
179
-
180
- if (false !== $locale) {
181
- setlocale(LC_NUMERIC, $locale);
182
- }
183
- } elseif (null === $value) {
184
- $this->raw('null');
185
- } elseif (is_bool($value)) {
186
- $this->raw($value ? 'true' : 'false');
187
- } elseif (is_array($value)) {
188
- $this->raw('[');
189
- $first = true;
190
- foreach ($value as $key => $v) {
191
- if (!$first) {
192
- $this->raw(', ');
193
- }
194
- $first = false;
195
- $this->repr($key);
196
- $this->raw(' => ');
197
- $this->repr($v);
198
- }
199
- $this->raw(']');
200
- } else {
201
- $this->string($value);
202
- }
203
-
204
- return $this;
205
- }
206
-
207
- /**
208
- * Adds debugging information.
209
- *
210
- * @return $this
211
- */
212
- public function addDebugInfo(Twig_NodeInterface $node)
213
- {
214
- if ($node->getTemplateLine() != $this->lastLine) {
215
- $this->write(sprintf("// line %d\n", $node->getTemplateLine()));
216
-
217
- // when mbstring.func_overload is set to 2
218
- // mb_substr_count() replaces substr_count()
219
- // but they have different signatures!
220
- if (((int) ini_get('mbstring.func_overload')) & 2) {
221
- @trigger_error('Support for having "mbstring.func_overload" different from 0 is deprecated version 1.29 and will be removed in 2.0.', E_USER_DEPRECATED);
222
-
223
- // this is much slower than the "right" version
224
- $this->sourceLine += mb_substr_count(mb_substr($this->source, $this->sourceOffset), "\n");
225
- } else {
226
- $this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
227
- }
228
- $this->sourceOffset = strlen($this->source);
229
- $this->debugInfo[$this->sourceLine] = $node->getTemplateLine();
230
-
231
- $this->lastLine = $node->getTemplateLine();
232
- }
233
-
234
- return $this;
235
- }
236
-
237
- public function getDebugInfo()
238
- {
239
- ksort($this->debugInfo);
240
-
241
- return $this->debugInfo;
242
- }
243
-
244
- /**
245
- * Indents the generated code.
246
- *
247
- * @param int $step The number of indentation to add
248
- *
249
- * @return $this
250
- */
251
- public function indent($step = 1)
252
- {
253
- $this->indentation += $step;
254
-
255
- return $this;
256
- }
257
-
258
- /**
259
- * Outdents the generated code.
260
- *
261
- * @param int $step The number of indentation to remove
262
- *
263
- * @return $this
264
- *
265
- * @throws LogicException When trying to outdent too much so the indentation would become negative
266
- */
267
- public function outdent($step = 1)
268
- {
269
- // can't outdent by more steps than the current indentation level
270
- if ($this->indentation < $step) {
271
- throw new LogicException('Unable to call outdent() as the indentation would become negative.');
272
- }
273
-
274
- $this->indentation -= $step;
275
-
276
- return $this;
277
- }
278
-
279
- public function getVarName()
280
- {
281
- return sprintf('__internal_%s', hash('sha256', __METHOD__.$this->varNameSalt++));
282
  }
283
  }
284
-
285
- class_alias('Twig_Compiler', 'Twig\Compiler', false);
286
- class_exists('Twig_Node');
1
  <?php
2
 
3
+ use Twig\Compiler;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Compiler');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Compiler extends Compiler
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
 
src/lib/vendor/twig/twig/lib/Twig/ContainerRuntimeLoader.php CHANGED
@@ -1,39 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- use Psr\Container\ContainerInterface;
13
 
14
- /**
15
- * Lazily loads Twig runtime implementations from a PSR-11 container.
16
- *
17
- * Note that the runtime services MUST use their class names as identifiers.
18
- *
19
- * @author Fabien Potencier <fabien@symfony.com>
20
- * @author Robin Chalas <robin.chalas@gmail.com>
21
- */
22
- class Twig_ContainerRuntimeLoader implements Twig_RuntimeLoaderInterface
23
- {
24
- private $container;
25
-
26
- public function __construct(ContainerInterface $container)
27
  {
28
- $this->container = $container;
29
- }
30
-
31
- public function load($class)
32
- {
33
- if ($this->container->has($class)) {
34
- return $this->container->get($class);
35
- }
36
  }
37
  }
38
-
39
- class_alias('Twig_ContainerRuntimeLoader', 'Twig\RuntimeLoader\ContainerRuntimeLoader', false);
1
  <?php
2
 
3
+ use Twig\RuntimeLoader\ContainerRuntimeLoader;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\RuntimeLoader\ContainerRuntimeLoader');
6
 
7
+ if (\false) {
8
+ class Twig_ContainerRuntimeLoader extends ContainerRuntimeLoader
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Environment.php CHANGED
@@ -1,1617 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Stores the Twig configuration.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Environment
18
- {
19
- const VERSION = '1.37.1';
20
- const VERSION_ID = 13701;
21
- const MAJOR_VERSION = 1;
22
- const MINOR_VERSION = 37;
23
- const RELEASE_VERSION = 1;
24
- const EXTRA_VERSION = '';
25
 
26
- protected $charset;
27
- protected $loader;
28
- protected $debug;
29
- protected $autoReload;
30
- protected $cache;
31
- protected $lexer;
32
- protected $parser;
33
- protected $compiler;
34
- protected $baseTemplateClass;
35
- protected $extensions;
36
- protected $parsers;
37
- protected $visitors;
38
- protected $filters;
39
- protected $tests;
40
- protected $functions;
41
- protected $globals;
42
- protected $runtimeInitialized = false;
43
- protected $extensionInitialized = false;
44
- protected $loadedTemplates;
45
- protected $strictVariables;
46
- protected $unaryOperators;
47
- protected $binaryOperators;
48
- protected $templateClassPrefix = '__TwigTemplate_';
49
- protected $functionCallbacks = [];
50
- protected $filterCallbacks = [];
51
- protected $staging;
52
-
53
- private $originalCache;
54
- private $bcWriteCacheFile = false;
55
- private $bcGetCacheFilename = false;
56
- private $lastModifiedExtension = 0;
57
- private $extensionsByClass = [];
58
- private $runtimeLoaders = [];
59
- private $runtimes = [];
60
- private $optionsHash;
61
- private $loading = [];
62
-
63
- /**
64
- * Constructor.
65
- *
66
- * Available options:
67
- *
68
- * * debug: When set to true, it automatically set "auto_reload" to true as
69
- * well (default to false).
70
- *
71
- * * charset: The charset used by the templates (default to UTF-8).
72
- *
73
- * * base_template_class: The base template class to use for generated
74
- * templates (default to Twig_Template).
75
- *
76
- * * cache: An absolute path where to store the compiled templates,
77
- * a Twig_Cache_Interface implementation,
78
- * or false to disable compilation cache (default).
79
- *
80
- * * auto_reload: Whether to reload the template if the original source changed.
81
- * If you don't provide the auto_reload option, it will be
82
- * determined automatically based on the debug value.
83
- *
84
- * * strict_variables: Whether to ignore invalid variables in templates
85
- * (default to false).
86
- *
87
- * * autoescape: Whether to enable auto-escaping (default to html):
88
- * * false: disable auto-escaping
89
- * * true: equivalent to html
90
- * * html, js: set the autoescaping to one of the supported strategies
91
- * * name: set the autoescaping strategy based on the template name extension
92
- * * PHP callback: a PHP callback that returns an escaping strategy based on the template "name"
93
- *
94
- * * optimizations: A flag that indicates which optimizations to apply
95
- * (default to -1 which means that all optimizations are enabled;
96
- * set it to 0 to disable).
97
- *
98
- * @param Twig_LoaderInterface $loader
99
- * @param array $options An array of options
100
- */
101
- public function __construct(Twig_LoaderInterface $loader = null, $options = [])
102
- {
103
- if (null !== $loader) {
104
- $this->setLoader($loader);
105
- } else {
106
- @trigger_error('Not passing a Twig_LoaderInterface as the first constructor argument of Twig_Environment is deprecated since version 1.21.', E_USER_DEPRECATED);
107
- }
108
-
109
- $options = array_merge([
110
- 'debug' => false,
111
- 'charset' => 'UTF-8',
112
- 'base_template_class' => 'Twig_Template',
113
- 'strict_variables' => false,
114
- 'autoescape' => 'html',
115
- 'cache' => false,
116
- 'auto_reload' => null,
117
- 'optimizations' => -1,
118
- ], $options);
119
-
120
- $this->debug = (bool) $options['debug'];
121
- $this->charset = strtoupper($options['charset']);
122
- $this->baseTemplateClass = $options['base_template_class'];
123
- $this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
124
- $this->strictVariables = (bool) $options['strict_variables'];
125
- $this->setCache($options['cache']);
126
-
127
- $this->addExtension(new Twig_Extension_Core());
128
- $this->addExtension(new Twig_Extension_Escaper($options['autoescape']));
129
- $this->addExtension(new Twig_Extension_Optimizer($options['optimizations']));
130
- $this->staging = new Twig_Extension_Staging();
131
-
132
- // For BC
133
- if (is_string($this->originalCache)) {
134
- $r = new ReflectionMethod($this, 'writeCacheFile');
135
- if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
136
- @trigger_error('The Twig_Environment::writeCacheFile method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED);
137
-
138
- $this->bcWriteCacheFile = true;
139
- }
140
-
141
- $r = new ReflectionMethod($this, 'getCacheFilename');
142
- if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
143
- @trigger_error('The Twig_Environment::getCacheFilename method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED);
144
-
145
- $this->bcGetCacheFilename = true;
146
- }
147
- }
148
- }
149
-
150
- /**
151
- * Gets the base template class for compiled templates.
152
- *
153
- * @return string The base template class name
154
- */
155
- public function getBaseTemplateClass()
156
- {
157
- return $this->baseTemplateClass;
158
- }
159
-
160
- /**
161
- * Sets the base template class for compiled templates.
162
- *
163
- * @param string $class The base template class name
164
- */
165
- public function setBaseTemplateClass($class)
166
- {
167
- $this->baseTemplateClass = $class;
168
- $this->updateOptionsHash();
169
- }
170
-
171
- /**
172
- * Enables debugging mode.
173
- */
174
- public function enableDebug()
175
- {
176
- $this->debug = true;
177
- $this->updateOptionsHash();
178
- }
179
-
180
- /**
181
- * Disables debugging mode.
182
- */
183
- public function disableDebug()
184
- {
185
- $this->debug = false;
186
- $this->updateOptionsHash();
187
- }
188
-
189
- /**
190
- * Checks if debug mode is enabled.
191
- *
192
- * @return bool true if debug mode is enabled, false otherwise
193
- */
194
- public function isDebug()
195
- {
196
- return $this->debug;
197
- }
198
-
199
- /**
200
- * Enables the auto_reload option.
201
- */
202
- public function enableAutoReload()
203
- {
204
- $this->autoReload = true;
205
- }
206
-
207
- /**
208
- * Disables the auto_reload option.
209
- */
210
- public function disableAutoReload()
211
- {
212
- $this->autoReload = false;
213
- }
214
-
215
- /**
216
- * Checks if the auto_reload option is enabled.
217
- *
218
- * @return bool true if auto_reload is enabled, false otherwise
219
- */
220
- public function isAutoReload()
221
- {
222
- return $this->autoReload;
223
- }
224
-
225
- /**
226
- * Enables the strict_variables option.
227
- */
228
- public function enableStrictVariables()
229
- {
230
- $this->strictVariables = true;
231
- $this->updateOptionsHash();
232
- }
233
-
234
- /**
235
- * Disables the strict_variables option.
236
- */
237
- public function disableStrictVariables()
238
- {
239
- $this->strictVariables = false;
240
- $this->updateOptionsHash();
241
- }
242
-
243
- /**
244
- * Checks if the strict_variables option is enabled.
245
- *
246
- * @return bool true if strict_variables is enabled, false otherwise
247
- */
248
- public function isStrictVariables()
249
- {
250
- return $this->strictVariables;
251
- }
252
-
253
- /**
254
- * Gets the current cache implementation.
255
- *
256
- * @param bool $original Whether to return the original cache option or the real cache instance
257
- *
258
- * @return Twig_CacheInterface|string|false A Twig_CacheInterface implementation,
259
- * an absolute path to the compiled templates,
260
- * or false to disable cache
261
- */
262
- public function getCache($original = true)
263
- {
264
- return $original ? $this->originalCache : $this->cache;
265
- }
266
-
267
- /**
268
- * Sets the current cache implementation.
269
- *
270
- * @param Twig_CacheInterface|string|false $cache A Twig_CacheInterface implementation,
271
- * an absolute path to the compiled templates,
272
- * or false to disable cache
273
- */
274
- public function setCache($cache)
275
- {
276
- if (is_string($cache)) {
277
- $this->originalCache = $cache;
278
- $this->cache = new Twig_Cache_Filesystem($cache);
279
- } elseif (false === $cache) {
280
- $this->originalCache = $cache;
281
- $this->cache = new Twig_Cache_Null();
282
- } elseif (null === $cache) {
283
- @trigger_error('Using "null" as the cache strategy is deprecated since version 1.23 and will be removed in Twig 2.0.', E_USER_DEPRECATED);
284
- $this->originalCache = false;
285
- $this->cache = new Twig_Cache_Null();
286
- } elseif ($cache instanceof Twig_CacheInterface) {
287
- $this->originalCache = $this->cache = $cache;
288
- } else {
289
- throw new LogicException(sprintf('Cache can only be a string, false, or a Twig_CacheInterface implementation.'));
290
- }
291
- }
292
-
293
- /**
294
- * Gets the cache filename for a given template.
295
- *
296
- * @param string $name The template name
297
- *
298
- * @return string|false The cache file name or false when caching is disabled
299
- *
300
- * @deprecated since 1.22 (to be removed in 2.0)
301
- */
302
- public function getCacheFilename($name)
303
- {
304
- @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
305
-
306
- $key = $this->cache->generateKey($name, $this->getTemplateClass($name));
307
-
308
- return !$key ? false : $key;
309
- }
310
-
311
- /**
312
- * Gets the template class associated with the given string.
313
- *
314
- * The generated template class is based on the following parameters:
315
- *
316
- * * The cache key for the given template;
317
- * * The currently enabled extensions;
318
- * * Whether the Twig C extension is available or not;
319
- * * PHP version;
320
- * * Twig version;
321
- * * Options with what environment was created.
322
- *
323
- * @param string $name The name for which to calculate the template class name
324
- * @param int|null $index The index if it is an embedded template
325
- *
326
- * @return string The template class name
327
- */
328
- public function getTemplateClass($name, $index = null)
329
- {
330
- $key = $this->getLoader()->getCacheKey($name).$this->optionsHash;
331
-
332
- return $this->templateClassPrefix.hash('sha256', $key).(null === $index ? '' : '_'.$index);
333
- }
334
-
335
- /**
336
- * Gets the template class prefix.
337
- *
338
- * @return string The template class prefix
339
- *
340
- * @deprecated since 1.22 (to be removed in 2.0)
341
- */
342
- public function getTemplateClassPrefix()
343
- {
344
- @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
345
-
346
- return $this->templateClassPrefix;
347
- }
348
-
349
- /**
350
- * Renders a template.
351
- *
352
- * @param string $name The template name
353
- * @param array $context An array of parameters to pass to the template
354
- *
355
- * @return string The rendered template
356
- *
357
- * @throws Twig_Error_Loader When the template cannot be found
358
- * @throws Twig_Error_Syntax When an error occurred during compilation
359
- * @throws Twig_Error_Runtime When an error occurred during rendering
360
- */
361
- public function render($name, array $context = [])
362
- {
363
- return $this->loadTemplate($name)->render($context);
364
- }
365
-
366
- /**
367
- * Displays a template.
368
- *
369
- * @param string $name The template name
370
- * @param array $context An array of parameters to pass to the template
371
- *
372
- * @throws Twig_Error_Loader When the template cannot be found
373
- * @throws Twig_Error_Syntax When an error occurred during compilation
374
- * @throws Twig_Error_Runtime When an error occurred during rendering
375
- */
376
- public function display($name, array $context = [])
377
- {
378
- $this->loadTemplate($name)->display($context);
379
- }
380
-
381
- /**
382
- * Loads a template.
383
- *
384
- * @param string|Twig_TemplateWrapper|Twig_Template $name The template name
385
- *
386
- * @throws Twig_Error_Loader When the template cannot be found
387
- * @throws Twig_Error_Runtime When a previously generated cache is corrupted
388
- * @throws Twig_Error_Syntax When an error occurred during compilation
389
- *
390
- * @return Twig_TemplateWrapper
391
- */
392
- public function load($name)
393
- {
394
- if ($name instanceof Twig_TemplateWrapper) {
395
- return $name;
396
- }
397
-
398
- if ($name instanceof Twig_Template) {
399
- return new Twig_TemplateWrapper($this, $name);
400
- }
401
-
402
- return new Twig_TemplateWrapper($this, $this->loadTemplate($name));
403
- }
404
-
405
- /**
406
- * Loads a template internal representation.
407
- *
408
- * This method is for internal use only and should never be called
409
- * directly.
410
- *
411
- * @param string $name The template name
412
- * @param int $index The index if it is an embedded template
413
- *
414
- * @return Twig_TemplateInterface A template instance representing the given template name
415
- *
416
- * @throws Twig_Error_Loader When the template cannot be found
417
- * @throws Twig_Error_Runtime When a previously generated cache is corrupted
418
- * @throws Twig_Error_Syntax When an error occurred during compilation
419
- *
420
- * @internal
421
- */
422
- public function loadTemplate($name, $index = null)
423
- {
424
- $cls = $mainCls = $this->getTemplateClass($name);
425
- if (null !== $index) {
426
- $cls .= '_'.$index;
427
- }
428
-
429
- if (isset($this->loadedTemplates[$cls])) {
430
- return $this->loadedTemplates[$cls];
431
- }
432
-
433
- if (!class_exists($cls, false)) {
434
- if ($this->bcGetCacheFilename) {
435
- $key = $this->getCacheFilename($name);
436
- } else {
437
- $key = $this->cache->generateKey($name, $mainCls);
438
- }
439
-
440
- if (!$this->isAutoReload() || $this->isTemplateFresh($name, $this->cache->getTimestamp($key))) {
441
- $this->cache->load($key);
442
- }
443
-
444
- if (!class_exists($cls, false)) {
445
- $loader = $this->getLoader();
446
- if (!$loader instanceof Twig_SourceContextLoaderInterface) {
447
- $source = new Twig_Source($loader->getSource($name), $name);
448
- } else {
449
- $source = $loader->getSourceContext($name);
450
- }
451
-
452
- $content = $this->compileSource($source);
453
-
454
- if ($this->bcWriteCacheFile) {
455
- $this->writeCacheFile($key, $content);
456
- } else {
457
- $this->cache->write($key, $content);
458
- $this->cache->load($key);
459
- }
460
-
461
- if (!class_exists($mainCls, false)) {
462
- /* Last line of defense if either $this->bcWriteCacheFile was used,
463
- * $this->cache is implemented as a no-op or we have a race condition
464
- * where the cache was cleared between the above calls to write to and load from
465
- * the cache.
466
- */
467
- eval('?>'.$content);
468
- }
469
- }
470
-
471
- if (!class_exists($cls, false)) {
472
- throw new Twig_Error_Runtime(sprintf('Failed to load Twig template "%s", index "%s": cache is corrupted.', $name, $index), -1, $source);
473
- }
474
- }
475
-
476
- if (!$this->runtimeInitialized) {
477
- $this->initRuntime();
478
- }
479
-
480
- if (isset($this->loading[$cls])) {
481
- throw new Twig_Error_Runtime(sprintf('Circular reference detected for Twig template "%s", path: %s.', $name, implode(' -> ', array_merge($this->loading, [$name]))));
482
- }
483
-
484
- $this->loading[$cls] = $name;
485
-
486
- try {
487
- $this->loadedTemplates[$cls] = new $cls($this);
488
- unset($this->loading[$cls]);
489
- } catch (\Exception $e) {
490
- unset($this->loading[$cls]);
491
-
492
- throw $e;
493
- }
494
-
495
- return $this->loadedTemplates[$cls];
496
- }
497
-
498
- /**
499
- * Creates a template from source.
500
- *
501
- * This method should not be used as a generic way to load templates.
502
- *
503
- * @param string $template The template name
504
- *
505
- * @return Twig_Template A template instance representing the given template name
506
- *
507
- * @throws Twig_Error_Loader When the template cannot be found
508
- * @throws Twig_Error_Syntax When an error occurred during compilation
509
- */
510
- public function createTemplate($template)
511
- {
512
- $name = sprintf('__string_template__%s', hash('sha256', $template, false));
513
-
514
- $loader = new Twig_Loader_Chain([
515
- new Twig_Loader_Array([$name => $template]),
516
- $current = $this->getLoader(),
517
- ]);
518
-
519
- $this->setLoader($loader);
520
- try {
521
- $template = $this->loadTemplate($name);
522
- } catch (Exception $e) {
523
- $this->setLoader($current);
524
-
525
- throw $e;
526
- } catch (Throwable $e) {
527
- $this->setLoader($current);
528
-
529
- throw $e;
530
- }
531
- $this->setLoader($current);
532
-
533
- return $template;
534
- }
535
-
536
- /**
537
- * Returns true if the template is still fresh.
538
- *
539
- * Besides checking the loader for freshness information,
540
- * this method also checks if the enabled extensions have
541
- * not changed.
542
- *
543
- * @param string $name The template name
544
- * @param int $time The last modification time of the cached template
545
- *
546
- * @return bool true if the template is fresh, false otherwise
547
- */
548
- public function isTemplateFresh($name, $time)
549
- {
550
- if (0 === $this->lastModifiedExtension) {
551
- foreach ($this->extensions as $extension) {
552
- $r = new ReflectionObject($extension);
553
- if (file_exists($r->getFileName()) && ($extensionTime = filemtime($r->getFileName())) > $this->lastModifiedExtension) {
554
- $this->lastModifiedExtension = $extensionTime;
555
- }
556
- }
557
- }
558
-
559
- return $this->lastModifiedExtension <= $time && $this->getLoader()->isFresh($name, $time);
560
- }
561
-
562
- /**
563
- * Tries to load a template consecutively from an array.
564
- *
565
- * Similar to loadTemplate() but it also accepts instances of Twig_Template and
566
- * Twig_TemplateWrapper, and an array of templates where each is tried to be loaded.
567
- *
568
- * @param string|Twig_Template|Twig_TemplateWrapper|array $names A template or an array of templates to try consecutively
569
- *
570
- * @return Twig_Template|Twig_TemplateWrapper
571
- *
572
- * @throws Twig_Error_Loader When none of the templates can be found
573
- * @throws Twig_Error_Syntax When an error occurred during compilation
574
- */
575
- public function resolveTemplate($names)
576
- {
577
- if (!is_array($names)) {
578
- $names = [$names];
579
- }
580
-
581
- foreach ($names as $name) {
582
- if ($name instanceof Twig_Template) {
583
- return $name;
584
- }
585
-
586
- if ($name instanceof Twig_TemplateWrapper) {
587
- return $name;
588
- }
589
-
590
- try {
591
- return $this->loadTemplate($name);
592
- } catch (Twig_Error_Loader $e) {
593
- }
594
- }
595
-
596
- if (1 === count($names)) {
597
- throw $e;
598
- }
599
-
600
- throw new Twig_Error_Loader(sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names)));
601
- }
602
-
603
- /**
604
- * Clears the internal template cache.
605
- *
606
- * @deprecated since 1.18.3 (to be removed in 2.0)
607
- */
608
- public function clearTemplateCache()
609
- {
610
- @trigger_error(sprintf('The %s method is deprecated since version 1.18.3 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
611
-
612
- $this->loadedTemplates = [];
613
- }
614
-
615
- /**
616
- * Clears the template cache files on the filesystem.
617
- *
618
- * @deprecated since 1.22 (to be removed in 2.0)
619
- */
620
- public function clearCacheFiles()
621
- {
622
- @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
623
-
624
- if (is_string($this->originalCache)) {
625
- foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->originalCache), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
626
- if ($file->isFile()) {
627
- @unlink($file->getPathname());
628
- }
629
- }
630
- }
631
- }
632
-
633
- /**
634
- * Gets the Lexer instance.
635
- *
636
- * @return Twig_LexerInterface
637
- *
638
- * @deprecated since 1.25 (to be removed in 2.0)
639
- */
640
- public function getLexer()
641
- {
642
- @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED);
643
-
644
- if (null === $this->lexer) {
645
- $this->lexer = new Twig_Lexer($this);
646
- }
647
-
648
- return $this->lexer;
649
- }
650
-
651
- public function setLexer(Twig_LexerInterface $lexer)
652
- {
653
- $this->lexer = $lexer;
654
- }
655
-
656
- /**
657
- * Tokenizes a source code.
658
- *
659
- * @param string|Twig_Source $source The template source code
660
- * @param string $name The template name (deprecated)
661
- *
662
- * @return Twig_TokenStream
663
- *
664
- * @throws Twig_Error_Syntax When the code is syntactically wrong
665
- */
666
- public function tokenize($source, $name = null)
667
- {
668
- if (!$source instanceof Twig_Source) {
669
- @trigger_error(sprintf('Passing a string as the $source argument of %s() is deprecated since version 1.27. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED);
670
- $source = new Twig_Source($source, $name);
671
- }
672
-
673
- if (null === $this->lexer) {
674
- $this->lexer = new Twig_Lexer($this);
675
- }
676
-
677
- return $this->lexer->tokenize($source);
678
- }
679
-
680
- /**
681
- * Gets the Parser instance.
682
- *
683
- * @return Twig_ParserInterface
684
- *
685
- * @deprecated since 1.25 (to be removed in 2.0)
686
- */
687
- public function getParser()
688
- {
689
- @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED);
690
-
691
- if (null === $this->parser) {
692
- $this->parser = new Twig_Parser($this);
693
- }
694
-
695
- return $this->parser;
696
- }
697
-
698
- public function setParser(Twig_ParserInterface $parser)
699
- {
700
- $this->parser = $parser;
701
- }
702
-
703
- /**
704
- * Converts a token stream to a node tree.
705
- *
706
- * @return Twig_Node_Module
707
- *
708
- * @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong
709
- */
710
- public function parse(Twig_TokenStream $stream)
711
- {
712
- if (null === $this->parser) {
713
- $this->parser = new Twig_Parser($this);
714
- }
715
-
716
- return $this->parser->parse($stream);
717
- }
718
-
719
- /**
720
- * Gets the Compiler instance.
721
- *
722
- * @return Twig_CompilerInterface
723
- *
724
- * @deprecated since 1.25 (to be removed in 2.0)
725
- */
726
- public function getCompiler()
727
- {
728
- @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED);
729
-
730
- if (null === $this->compiler) {
731
- $this->compiler = new Twig_Compiler($this);
732
- }
733
-
734
- return $this->compiler;
735
- }
736
-
737
- public function setCompiler(Twig_CompilerInterface $compiler)
738
- {
739
- $this->compiler = $compiler;
740
- }
741
-
742
- /**
743
- * Compiles a node and returns the PHP code.
744
- *
745
- * @return string The compiled PHP source code
746
- */
747
- public function compile(Twig_NodeInterface $node)
748
- {
749
- if (null === $this->compiler) {
750
- $this->compiler = new Twig_Compiler($this);
751
- }
752
-
753
- return $this->compiler->compile($node)->getSource();
754
- }
755
-
756
- /**
757
- * Compiles a template source code.
758
- *
759
- * @param string|Twig_Source $source The template source code
760
- * @param string $name The template name (deprecated)
761
- *
762
- * @return string The compiled PHP source code
763
- *
764
- * @throws Twig_Error_Syntax When there was an error during tokenizing, parsing or compiling
765
- */
766
- public function compileSource($source, $name = null)
767
- {
768
- if (!$source instanceof Twig_Source) {
769
- @trigger_error(sprintf('Passing a string as the $source argument of %s() is deprecated since version 1.27. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED);
770
- $source = new Twig_Source($source, $name);
771
- }
772
-
773
- try {
774
- return $this->compile($this->parse($this->tokenize($source)));
775
- } catch (Twig_Error $e) {
776
- $e->setSourceContext($source);
777
- throw $e;
778
- } catch (Exception $e) {
779
- throw new Twig_Error_Syntax(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $source, $e);
780
- }
781
- }
782
-
783
- public function setLoader(Twig_LoaderInterface $loader)
784
- {
785
- if (!$loader instanceof Twig_SourceContextLoaderInterface && 0 !== strpos(get_class($loader), 'Mock_')) {
786
- @trigger_error(sprintf('Twig loader "%s" should implement Twig_SourceContextLoaderInterface since version 1.27.', get_class($loader)), E_USER_DEPRECATED);
787
- }
788
-
789
- $this->loader = $loader;
790
- }
791
-
792
- /**
793
- * Gets the Loader instance.
794
- *
795
- * @return Twig_LoaderInterface
796
- */
797
- public function getLoader()
798
- {
799
- if (null === $this->loader) {
800
- throw new LogicException('You must set a loader first.');
801
- }
802
-
803
- return $this->loader;
804
- }
805
-
806
- /**
807
- * Sets the default template charset.
808
- *
809
- * @param string $charset The default charset
810
- */
811
- public function setCharset($charset)
812
- {
813
- $this->charset = strtoupper($charset);
814
- }
815
-
816
- /**
817
- * Gets the default template charset.
818
- *
819
- * @return string The default charset
820
- */
821
- public function getCharset()
822
- {
823
- return $this->charset;
824
- }
825
-
826
- /**
827
- * Initializes the runtime environment.
828
- *
829
- * @deprecated since 1.23 (to be removed in 2.0)
830
- */
831
- public function initRuntime()
832
- {
833
- $this->runtimeInitialized = true;
834
-
835
- foreach ($this->getExtensions() as $name => $extension) {
836
- if (!$extension instanceof Twig_Extension_InitRuntimeInterface) {
837
- $m = new ReflectionMethod($extension, 'initRuntime');
838
-
839
- if ('Twig_Extension' !== $m->getDeclaringClass()->getName()) {
840
- @trigger_error(sprintf('Defining the initRuntime() method in the "%s" extension is deprecated since version 1.23. Use the `needs_environment` option to get the Twig_Environment instance in filters, functions, or tests; or explicitly implement Twig_Extension_InitRuntimeInterface if needed (not recommended).', $name), E_USER_DEPRECATED);
841
- }
842
- }
843
-
844
- $extension->initRuntime($this);
845
- }
846
- }
847
-
848
- /**
849
- * Returns true if the given extension is registered.
850
- *
851
- * @param string $class The extension class name
852
- *
853
- * @return bool Whether the extension is registered or not
854
- */
855
- public function hasExtension($class)
856
- {
857
- $class = ltrim($class, '\\');
858
- if (!isset($this->extensionsByClass[$class]) && class_exists($class, false)) {
859
- // For BC/FC with namespaced aliases
860
- $class = new ReflectionClass($class);
861
- $class = $class->name;
862
- }
863
-
864
- if (isset($this->extensions[$class])) {
865
- if ($class !== get_class($this->extensions[$class])) {
866
- @trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED);
867
- }
868
-
869
- return true;
870
- }
871
-
872
- return isset($this->extensionsByClass[$class]);
873
- }
874
-
875
- /**
876
- * Adds a runtime loader.
877
- */
878
- public function addRuntimeLoader(Twig_RuntimeLoaderInterface $loader)
879
- {
880
- $this->runtimeLoaders[] = $loader;
881
- }
882
-
883
- /**
884
- * Gets an extension by class name.
885
- *
886
- * @param string $class The extension class name
887
- *
888
- * @return Twig_ExtensionInterface
889
- */
890
- public function getExtension($class)
891
- {
892
- $class = ltrim($class, '\\');
893
- if (!isset($this->extensionsByClass[$class]) && class_exists($class, false)) {
894
- // For BC/FC with namespaced aliases
895
- $class = new ReflectionClass($class);
896
- $class = $class->name;
897
- }
898
-
899
- if (isset($this->extensions[$class])) {
900
- if ($class !== get_class($this->extensions[$class])) {
901
- @trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED);
902
- }
903
-
904
- return $this->extensions[$class];
905
- }
906
-
907
- if (!isset($this->extensionsByClass[$class])) {
908
- throw new Twig_Error_Runtime(sprintf('The "%s" extension is not enabled.', $class));
909
- }
910
-
911
- return $this->extensionsByClass[$class];
912
- }
913
-
914
- /**
915
- * Returns the runtime implementation of a Twig element (filter/function/test).
916
- *
917
- * @param string $class A runtime class name
918
- *
919
- * @return object The runtime implementation
920
- *
921
- * @throws Twig_Error_Runtime When the template cannot be found
922
- */
923
- public function getRuntime($class)
924
- {
925
- if (isset($this->runtimes[$class])) {
926
- return $this->runtimes[$class];
927
- }
928
-
929
- foreach ($this->runtimeLoaders as $loader) {
930
- if (null !== $runtime = $loader->load($class)) {
931
- return $this->runtimes[$class] = $runtime;
932
- }
933
- }
934
-
935
- throw new Twig_Error_Runtime(sprintf('Unable to load the "%s" runtime.', $class));
936
- }
937
-
938
- public function addExtension(Twig_ExtensionInterface $extension)
939
- {
940
- if ($this->extensionInitialized) {
941
- throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName()));
942
- }
943
-
944
- $class = get_class($extension);
945
- if ($class !== $extension->getName()) {
946
- if (isset($this->extensions[$extension->getName()])) {
947
- unset($this->extensions[$extension->getName()], $this->extensionsByClass[$class]);
948
- @trigger_error(sprintf('The possibility to register the same extension twice ("%s") is deprecated since version 1.23 and will be removed in Twig 2.0. Use proper PHP inheritance instead.', $extension->getName()), E_USER_DEPRECATED);
949
- }
950
- }
951
-
952
- $this->lastModifiedExtension = 0;
953
- $this->extensionsByClass[$class] = $extension;
954
- $this->extensions[$extension->getName()] = $extension;
955
- $this->updateOptionsHash();
956
- }
957
-
958
- /**
959
- * Removes an extension by name.
960
- *
961
- * This method is deprecated and you should not use it.
962
- *
963
- * @param string $name The extension name
964
- *
965
- * @deprecated since 1.12 (to be removed in 2.0)
966
- */
967
- public function removeExtension($name)
968
- {
969
- @trigger_error(sprintf('The %s method is deprecated since version 1.12 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
970
-
971
- if ($this->extensionInitialized) {
972
- throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name));
973
- }
974
-
975
- $class = ltrim($name, '\\');
976
- if (!isset($this->extensionsByClass[$class]) && class_exists($class, false)) {
977
- // For BC/FC with namespaced aliases
978
- $class = new ReflectionClass($class);
979
- $class = $class->name;
980
- }
981
-
982
- if (isset($this->extensions[$class])) {
983
- if ($class !== get_class($this->extensions[$class])) {
984
- @trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED);
985
- }
986
-
987
- unset($this->extensions[$class]);
988
- }
989
-
990
- unset($this->extensions[$class]);
991
- $this->updateOptionsHash();
992
- }
993
-
994
- /**
995
- * Registers an array of extensions.
996
- *
997
- * @param array $extensions An array of extensions
998
- */
999
- public function setExtensions(array $extensions)
1000
- {
1001
- foreach ($extensions as $extension) {
1002
- $this->addExtension($extension);
1003
- }
1004
- }
1005
-
1006
- /**
1007
- * Returns all registered extensions.
1008
- *
1009
- * @return Twig_ExtensionInterface[] An array of extensions (keys are for internal usage only and should not be relied on)
1010
- */
1011
- public function getExtensions()
1012
- {
1013
- return $this->extensions;
1014
- }
1015
-
1016
- public function addTokenParser(Twig_TokenParserInterface $parser)
1017
- {
1018
- if ($this->extensionInitialized) {
1019
- throw new LogicException('Unable to add a token parser as extensions have already been initialized.');
1020
- }
1021
-
1022
- $this->staging->addTokenParser($parser);
1023
- }
1024
-
1025
- /**
1026
- * Gets the registered Token Parsers.
1027
- *
1028
- * @return Twig_TokenParserBrokerInterface
1029
- *
1030
- * @internal
1031
- */
1032
- public function getTokenParsers()
1033
- {
1034
- if (!$this->extensionInitialized) {
1035
- $this->initExtensions();
1036
- }
1037
-
1038
- return $this->parsers;
1039
- }
1040
-
1041
- /**
1042
- * Gets registered tags.
1043
- *
1044
- * Be warned that this method cannot return tags defined by Twig_TokenParserBrokerInterface classes.
1045
- *
1046
- * @return Twig_TokenParserInterface[]
1047
- *
1048
- * @internal
1049
- */
1050
- public function getTags()
1051
- {
1052
- $tags = [];
1053
- foreach ($this->getTokenParsers()->getParsers() as $parser) {
1054
- if ($parser instanceof Twig_TokenParserInterface) {
1055
- $tags[$parser->getTag()] = $parser;
1056
- }
1057
- }
1058
-
1059
- return $tags;
1060
- }
1061
-
1062
- public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
1063
- {
1064
- if ($this->extensionInitialized) {
1065
- throw new LogicException('Unable to add a node visitor as extensions have already been initialized.');
1066
- }
1067
-
1068
- $this->staging->addNodeVisitor($visitor);
1069
- }
1070
-
1071
- /**
1072
- * Gets the registered Node Visitors.
1073
- *
1074
- * @return Twig_NodeVisitorInterface[]
1075
- *
1076
- * @internal
1077
- */
1078
- public function getNodeVisitors()
1079
- {
1080
- if (!$this->extensionInitialized) {
1081
- $this->initExtensions();
1082
- }
1083
-
1084
- return $this->visitors;
1085
- }
1086
-
1087
- /**
1088
- * Registers a Filter.
1089
- *
1090
- * @param string|Twig_SimpleFilter $name The filter name or a Twig_SimpleFilter instance
1091
- * @param Twig_FilterInterface|Twig_SimpleFilter $filter
1092
- */
1093
- public function addFilter($name, $filter = null)
1094
- {
1095
- if (!$name instanceof Twig_SimpleFilter && !($filter instanceof Twig_SimpleFilter || $filter instanceof Twig_FilterInterface)) {
1096
- throw new LogicException('A filter must be an instance of Twig_FilterInterface or Twig_SimpleFilter.');
1097
- }
1098
-
1099
- if ($name instanceof Twig_SimpleFilter) {
1100
- $filter = $name;
1101
- $name = $filter->getName();
1102
- } else {
1103
- @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleFilter" instead when defining filter "%s".', __METHOD__, $name), E_USER_DEPRECATED);
1104
- }
1105
-
1106
- if ($this->extensionInitialized) {
1107
- throw new LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name));
1108
- }
1109
-
1110
- $this->staging->addFilter($name, $filter);
1111
- }
1112
-
1113
- /**
1114
- * Get a filter by name.
1115
- *
1116
- * Subclasses may override this method and load filters differently;
1117
- * so no list of filters is available.
1118
- *
1119
- * @param string $name The filter name
1120
- *
1121
- * @return Twig_Filter|false A Twig_Filter instance or false if the filter does not exist
1122
- *
1123
- * @internal
1124
- */
1125
- public function getFilter($name)
1126
- {
1127
- if (!$this->extensionInitialized) {
1128
- $this->initExtensions();
1129
- }
1130
-
1131
- if (isset($this->filters[$name])) {
1132
- return $this->filters[$name];
1133
- }
1134
-
1135
- foreach ($this->filters as $pattern => $filter) {
1136
- $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
1137
-
1138
- if ($count) {
1139
- if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
1140
- array_shift($matches);
1141
- $filter->setArguments($matches);
1142
-
1143
- return $filter;
1144
- }
1145
- }
1146
- }
1147
-
1148
- foreach ($this->filterCallbacks as $callback) {
1149
- if (false !== $filter = call_user_func($callback, $name)) {
1150
- return $filter;
1151
- }
1152
- }
1153
-
1154
- return false;
1155
- }
1156
-
1157
- public function registerUndefinedFilterCallback($callable)
1158
- {
1159
- $this->filterCallbacks[] = $callable;
1160
- }
1161
-
1162
- /**
1163
- * Gets the registered Filters.
1164
- *
1165
- * Be warned that this method cannot return filters defined with registerUndefinedFilterCallback.
1166
- *
1167
- * @return Twig_FilterInterface[]
1168
- *
1169
- * @see registerUndefinedFilterCallback
1170
- *
1171
- * @internal
1172
- */
1173
- public function getFilters()
1174
- {
1175
- if (!$this->extensionInitialized) {
1176
- $this->initExtensions();
1177
- }
1178
-
1179
- return $this->filters;
1180
- }
1181
-
1182
- /**
1183
- * Registers a Test.
1184
- *
1185
- * @param string|Twig_SimpleTest $name The test name or a Twig_SimpleTest instance
1186
- * @param Twig_TestInterface|Twig_SimpleTest $test A Twig_TestInterface instance or a Twig_SimpleTest instance
1187
- */
1188
- public function addTest($name, $test = null)
1189
- {
1190
- if (!$name instanceof Twig_SimpleTest && !($test instanceof Twig_SimpleTest || $test instanceof Twig_TestInterface)) {
1191
- throw new LogicException('A test must be an instance of Twig_TestInterface or Twig_SimpleTest.');
1192
- }
1193
-
1194
- if ($name instanceof Twig_SimpleTest) {
1195
- $test = $name;
1196
- $name = $test->getName();
1197
- } else {
1198
- @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleTest" instead when defining test "%s".', __METHOD__, $name), E_USER_DEPRECATED);
1199
- }
1200
-
1201
- if ($this->extensionInitialized) {
1202
- throw new LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name));
1203
- }
1204
-
1205
- $this->staging->addTest($name, $test);
1206
- }
1207
-
1208
- /**
1209
- * Gets the registered Tests.
1210
- *
1211
- * @return Twig_TestInterface[]
1212
- *
1213
- * @internal
1214
- */
1215
- public function getTests()
1216
- {
1217
- if (!$this->extensionInitialized) {
1218
- $this->initExtensions();
1219
- }
1220
-
1221
- return $this->tests;
1222
- }
1223
-
1224
- /**
1225
- * Gets a test by name.
1226
- *
1227
- * @param string $name The test name
1228
- *
1229
- * @return Twig_Test|false A Twig_Test instance or false if the test does not exist
1230
- *
1231
- * @internal
1232
- */
1233
- public function getTest($name)
1234
- {
1235
- if (!$this->extensionInitialized) {
1236
- $this->initExtensions();
1237
- }
1238
-
1239
- if (isset($this->tests[$name])) {
1240
- return $this->tests[$name];
1241
- }
1242
-
1243
- foreach ($this->tests as $pattern => $test) {
1244
- $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
1245
-
1246
- if ($count) {
1247
- if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
1248
- array_shift($matches);
1249
- $test->setArguments($matches);
1250
-
1251
- return $test;
1252
- }
1253
- }
1254
- }
1255
-
1256
- return false;
1257
- }
1258
-
1259
- /**
1260
- * Registers a Function.
1261
- *
1262
- * @param string|Twig_SimpleFunction $name The function name or a Twig_SimpleFunction instance
1263
- * @param Twig_FunctionInterface|Twig_SimpleFunction $function
1264
- */
1265
- public function addFunction($name, $function = null)
1266
- {
1267
- if (!$name instanceof Twig_SimpleFunction && !($function instanceof Twig_SimpleFunction || $function instanceof Twig_FunctionInterface)) {
1268
- throw new LogicException('A function must be an instance of Twig_FunctionInterface or Twig_SimpleFunction.');
1269
- }
1270
-
1271
- if ($name instanceof Twig_SimpleFunction) {
1272
- $function = $name;
1273
- $name = $function->getName();
1274
- } else {
1275
- @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleFunction" instead when defining function "%s".', __METHOD__, $name), E_USER_DEPRECATED);
1276
- }
1277
-
1278
- if ($this->extensionInitialized) {
1279
- throw new LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name));
1280
- }
1281
-
1282
- $this->staging->addFunction($name, $function);
1283
- }
1284
-
1285
- /**
1286
- * Get a function by name.
1287
- *
1288
- * Subclasses may override this method and load functions differently;
1289
- * so no list of functions is available.
1290
- *
1291
- * @param string $name function name
1292
- *
1293
- * @return Twig_Function|false A Twig_Function instance or false if the function does not exist
1294
- *
1295
- * @internal
1296
- */
1297
- public function getFunction($name)
1298
- {
1299
- if (!$this->extensionInitialized) {
1300
- $this->initExtensions();
1301
- }
1302
-
1303
- if (isset($this->functions[$name])) {
1304
- return $this->functions[$name];
1305
- }
1306
-
1307
- foreach ($this->functions as $pattern => $function) {
1308
- $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
1309
-
1310
- if ($count) {
1311
- if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
1312
- array_shift($matches);
1313
- $function->setArguments($matches);
1314
-
1315
- return $function;
1316
- }
1317
- }
1318
- }
1319
-
1320
- foreach ($this->functionCallbacks as $callback) {
1321
- if (false !== $function = call_user_func($callback, $name)) {
1322
- return $function;
1323
- }
1324
- }
1325
-
1326
- return false;
1327
- }
1328
-
1329
- public function registerUndefinedFunctionCallback($callable)
1330
- {
1331
- $this->functionCallbacks[] = $callable;
1332
- }
1333
-
1334
- /**
1335
- * Gets registered functions.
1336
- *
1337
- * Be warned that this method cannot return functions defined with registerUndefinedFunctionCallback.
1338
- *
1339
- * @return Twig_FunctionInterface[]
1340
- *
1341
- * @see registerUndefinedFunctionCallback
1342
- *
1343
- * @internal
1344
- */
1345
- public function getFunctions()
1346
- {
1347
- if (!$this->extensionInitialized) {
1348
- $this->initExtensions();
1349
- }
1350
-
1351
- return $this->functions;
1352
- }
1353
-
1354
- /**
1355
- * Registers a Global.
1356
- *
1357
- * New globals can be added before compiling or rendering a template;
1358
- * but after, you can only update existing globals.
1359
- *
1360
- * @param string $name The global name
1361
- * @param mixed $value The global value
1362
- */
1363
- public function addGlobal($name, $value)
1364
- {
1365
- if ($this->extensionInitialized || $this->runtimeInitialized) {
1366
- if (null === $this->globals) {
1367
- $this->globals = $this->initGlobals();
1368
- }
1369
-
1370
- if (!array_key_exists($name, $this->globals)) {
1371
- // The deprecation notice must be turned into the following exception in Twig 2.0
1372
- @trigger_error(sprintf('Registering global variable "%s" at runtime or when the extensions have already been initialized is deprecated since version 1.21.', $name), E_USER_DEPRECATED);
1373
- //throw new LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name));
1374
- }
1375
- }
1376
-
1377
- if ($this->extensionInitialized || $this->runtimeInitialized) {
1378
- // update the value
1379
- $this->globals[$name] = $value;
1380
- } else {
1381
- $this->staging->addGlobal($name, $value);
1382
- }
1383
- }
1384
-
1385
- /**
1386
- * Gets the registered Globals.
1387
- *
1388
- * @return array An array of globals
1389
- *
1390
- * @internal
1391
- */
1392
- public function getGlobals()
1393
- {
1394
- if (!$this->runtimeInitialized && !$this->extensionInitialized) {
1395
- return $this->initGlobals();
1396
- }
1397
-
1398
- if (null === $this->globals) {
1399
- $this->globals = $this->initGlobals();
1400
- }
1401
-
1402
- return $this->globals;
1403
- }
1404
-
1405
- /**
1406
- * Merges a context with the defined globals.
1407
- *
1408
- * @param array $context An array representing the context
1409
- *
1410
- * @return array The context merged with the globals
1411
- */
1412
- public function mergeGlobals(array $context)
1413
- {
1414
- // we don't use array_merge as the context being generally
1415
- // bigger than globals, this code is faster.
1416
- foreach ($this->getGlobals() as $key => $value) {
1417
- if (!array_key_exists($key, $context)) {
1418
- $context[$key] = $value;
1419
- }
1420
- }
1421
-
1422
- return $context;
1423
- }
1424
-
1425
- /**
1426
- * Gets the registered unary Operators.
1427
- *
1428
- * @return array An array of unary operators
1429
- *
1430
- * @internal
1431
- */
1432
- public function getUnaryOperators()
1433
- {
1434
- if (!$this->extensionInitialized) {
1435
- $this->initExtensions();
1436
- }
1437
-
1438
- return $this->unaryOperators;
1439
- }
1440
-
1441
- /**
1442
- * Gets the registered binary Operators.
1443
- *
1444
- * @return array An array of binary operators
1445
- *
1446
- * @internal
1447
- */
1448
- public function getBinaryOperators()
1449
  {
1450
- if (!$this->extensionInitialized) {
1451
- $this->initExtensions();
1452
- }
1453
-
1454
- return $this->binaryOperators;
1455
- }
1456
-
1457
- /**
1458
- * @deprecated since 1.23 (to be removed in 2.0)
1459
- */
1460
- public function computeAlternatives($name, $items)
1461
- {
1462
- @trigger_error(sprintf('The %s method is deprecated since version 1.23 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
1463
-
1464
- return Twig_Error_Syntax::computeAlternatives($name, $items);
1465
- }
1466
-
1467
- /**
1468
- * @internal
1469
- */
1470
- protected function initGlobals()
1471
- {
1472
- $globals = [];
1473
- foreach ($this->extensions as $name => $extension) {
1474
- if (!$extension instanceof Twig_Extension_GlobalsInterface) {
1475
- $m = new ReflectionMethod($extension, 'getGlobals');
1476
-
1477
- if ('Twig_Extension' !== $m->getDeclaringClass()->getName()) {
1478
- @trigger_error(sprintf('Defining the getGlobals() method in the "%s" extension without explicitly implementing Twig_Extension_GlobalsInterface is deprecated since version 1.23.', $name), E_USER_DEPRECATED);
1479
- }
1480
- }
1481
-
1482
- $extGlob = $extension->getGlobals();
1483
- if (!is_array($extGlob)) {
1484
- throw new UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', get_class($extension)));
1485
- }
1486
-
1487
- $globals[] = $extGlob;
1488
- }
1489
-
1490
- $globals[] = $this->staging->getGlobals();
1491
-
1492
- return call_user_func_array('array_merge', $globals);
1493
- }
1494
-
1495
- /**
1496
- * @internal
1497
- */
1498
- protected function initExtensions()
1499
- {
1500
- if ($this->extensionInitialized) {
1501
- return;
1502
- }
1503
-
1504
- $this->parsers = new Twig_TokenParserBroker([], [], false);
1505
- $this->filters = [];
1506
- $this->functions = [];
1507
- $this->tests = [];
1508
- $this->visitors = [];
1509
- $this->unaryOperators = [];
1510
- $this->binaryOperators = [];
1511
-
1512
- foreach ($this->extensions as $extension) {
1513
- $this->initExtension($extension);
1514
- }
1515
- $this->initExtension($this->staging);
1516
- // Done at the end only, so that an exception during initialization does not mark the environment as initialized when catching the exception
1517
- $this->extensionInitialized = true;
1518
- }
1519
-
1520
- /**
1521
- * @internal
1522
- */
1523
- protected function initExtension(Twig_ExtensionInterface $extension)
1524
- {
1525
- // filters
1526
- foreach ($extension->getFilters() as $name => $filter) {
1527
- if ($filter instanceof Twig_SimpleFilter) {
1528
- $name = $filter->getName();
1529
- } else {
1530
- @trigger_error(sprintf('Using an instance of "%s" for filter "%s" is deprecated since version 1.21. Use Twig_SimpleFilter instead.', get_class($filter), $name), E_USER_DEPRECATED);
1531
- }
1532
-
1533
- $this->filters[$name] = $filter;
1534
- }
1535
-
1536
- // functions
1537
- foreach ($extension->getFunctions() as $name => $function) {
1538
- if ($function instanceof Twig_SimpleFunction) {
1539
- $name = $function->getName();
1540
- } else {
1541
- @trigger_error(sprintf('Using an instance of "%s" for function "%s" is deprecated since version 1.21. Use Twig_SimpleFunction instead.', get_class($function), $name), E_USER_DEPRECATED);
1542
- }
1543
-
1544
- $this->functions[$name] = $function;
1545
- }
1546
-
1547
- // tests
1548
- foreach ($extension->getTests() as $name => $test) {
1549
- if ($test instanceof Twig_SimpleTest) {
1550
- $name = $test->getName();
1551
- } else {
1552
- @trigger_error(sprintf('Using an instance of "%s" for test "%s" is deprecated since version 1.21. Use Twig_SimpleTest instead.', get_class($test), $name), E_USER_DEPRECATED);
1553
- }
1554
-
1555
- $this->tests[$name] = $test;
1556
- }
1557
-
1558
- // token parsers
1559
- foreach ($extension->getTokenParsers() as $parser) {
1560
- if ($parser instanceof Twig_TokenParserInterface) {
1561
- $this->parsers->addTokenParser($parser);
1562
- } elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
1563
- @trigger_error('Registering a Twig_TokenParserBrokerInterface instance is deprecated since version 1.21.', E_USER_DEPRECATED);
1564
-
1565
- $this->parsers->addTokenParserBroker($parser);
1566
- } else {
1567
- throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances.');
1568
- }
1569
- }
1570
-
1571
- // node visitors
1572
- foreach ($extension->getNodeVisitors() as $visitor) {
1573
- $this->visitors[] = $visitor;
1574
- }
1575
-
1576
- // operators
1577
- if ($operators = $extension->getOperators()) {
1578
- if (!is_array($operators)) {
1579
- throw new InvalidArgumentException(sprintf('"%s::getOperators()" must return an array with operators, got "%s".', get_class($extension), is_object($operators) ? get_class($operators) : gettype($operators).(is_resource($operators) ? '' : '#'.$operators)));
1580
- }
1581
-
1582
- if (2 !== count($operators)) {
1583
- throw new InvalidArgumentException(sprintf('"%s::getOperators()" must return an array of 2 elements, got %d.', get_class($extension), count($operators)));
1584
- }
1585
-
1586
- $this->unaryOperators = array_merge($this->unaryOperators, $operators[0]);
1587
- $this->binaryOperators = array_merge($this->binaryOperators, $operators[1]);
1588
- }
1589
- }
1590
-
1591
- /**
1592
- * @deprecated since 1.22 (to be removed in 2.0)
1593
- */
1594
- protected function writeCacheFile($file, $content)
1595
- {
1596
- $this->cache->write($file, $content);
1597
- }
1598
-
1599
- private function updateOptionsHash()
1600
- {
1601
- $hashParts = array_merge(
1602
- array_keys($this->extensions),
1603
- [
1604
- (int) function_exists('twig_template_get_attributes'),
1605
- PHP_MAJOR_VERSION,
1606
- PHP_MINOR_VERSION,
1607
- self::VERSION,
1608
- (int) $this->debug,
1609
- $this->baseTemplateClass,
1610
- (int) $this->strictVariables,
1611
- ]
1612
- );
1613
- $this->optionsHash = implode(':', $hashParts);
1614
  }
1615
  }
1616
-
1617
- class_alias('Twig_Environment', 'Twig\Environment', false);
1
  <?php
2
 
3
+ use Twig\Environment;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Environment');
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Environment extends Environment
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Error.php CHANGED
@@ -1,333 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Twig base exception.
14
- *
15
- * This exception class and its children must only be used when
16
- * an error occurs during the loading of a template, when a syntax error
17
- * is detected in a template, or when rendering a template. Other
18
- * errors must use regular PHP exception classes (like when the template
19
- * cache directory is not writable for instance).
20
- *
21
- * To help debugging template issues, this class tracks the original template
22
- * name and line where the error occurred.
23
- *
24
- * Whenever possible, you must set these information (original template name
25
- * and line number) yourself by passing them to the constructor. If some or all
26
- * these information are not available from where you throw the exception, then
27
- * this class will guess them automatically (when the line number is set to -1
28
- * and/or the name is set to null). As this is a costly operation, this
29
- * can be disabled by passing false for both the name and the line number
30
- * when creating a new instance of this class.
31
- *
32
- * @author Fabien Potencier <fabien@symfony.com>
33
- */
34
- class Twig_Error extends Exception
35
- {
36
- protected $lineno;
37
- // to be renamed to name in 2.0
38
- protected $filename;
39
- protected $rawMessage;
40
 
41
- private $sourcePath;
42
- private $sourceCode;
43
-
44
- /**
45
- * Constructor.
46
- *
47
- * Set both the line number and the name to false to
48
- * disable automatic guessing of the original template name
49
- * and line number.
50
- *
51
- * Set the line number to -1 to enable its automatic guessing.
52
- * Set the name to null to enable its automatic guessing.
53
- *
54
- * By default, automatic guessing is enabled.
55
- *
56
- * @param string $message The error message
57
- * @param int $lineno The template line where the error occurred
58
- * @param Twig_Source|string|null $source The source context where the error occurred
59
- * @param Exception $previous The previous exception
60
- */
61
- public function __construct($message, $lineno = -1, $source = null, Exception $previous = null)
62
- {
63
- if (null === $source) {
64
- $name = null;
65
- } elseif (!$source instanceof Twig_Source) {
66
- // for compat with the Twig C ext., passing the template name as string is accepted
67
- $name = $source;
68
- } else {
69
- $name = $source->getName();
70
- $this->sourceCode = $source->getCode();
71
- $this->sourcePath = $source->getPath();
72
- }
73
- parent::__construct('', 0, $previous);
74
-
75
- $this->lineno = $lineno;
76
- $this->filename = $name;
77
-
78
- if (-1 === $lineno || null === $name || null === $this->sourcePath) {
79
- $this->guessTemplateInfo();
80
- }
81
-
82
- $this->rawMessage = $message;
83
-
84
- $this->updateRepr();
85
- }
86
-
87
- /**
88
- * Gets the raw message.
89
- *
90
- * @return string The raw message
91
- */
92
- public function getRawMessage()
93
- {
94
- return $this->rawMessage;
95
- }
96
-
97
- /**
98
- * Gets the logical name where the error occurred.
99
- *
100
- * @return string The name
101
- *
102
- * @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead.
103
- */
104
- public function getTemplateFile()
105
- {
106
- @trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
107
-
108
- return $this->filename;
109
- }
110
-
111
- /**
112
- * Sets the logical name where the error occurred.
113
- *
114
- * @param string $name The name
115
- *
116
- * @deprecated since 1.27 (to be removed in 2.0). Use setSourceContext() instead.
117
- */
118
- public function setTemplateFile($name)
119
- {
120
- @trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use setSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
121
-
122
- $this->filename = $name;
123
-
124
- $this->updateRepr();
125
- }
126
-
127
- /**
128
- * Gets the logical name where the error occurred.
129
- *
130
- * @return string The name
131
- *
132
- * @deprecated since 1.29 (to be removed in 2.0). Use getSourceContext() instead.
133
- */
134
- public function getTemplateName()
135
- {
136
- @trigger_error(sprintf('The "%s" method is deprecated since version 1.29 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
137
-
138
- return $this->filename;
139
- }
140
-
141
- /**
142
- * Sets the logical name where the error occurred.
143
- *
144
- * @param string $name The name
145
- *
146
- * @deprecated since 1.29 (to be removed in 2.0). Use setSourceContext() instead.
147
- */
148
- public function setTemplateName($name)
149
- {
150
- @trigger_error(sprintf('The "%s" method is deprecated since version 1.29 and will be removed in 2.0. Use setSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
151
-
152
- $this->filename = $name;
153
- $this->sourceCode = $this->sourcePath = null;
154
-
155
- $this->updateRepr();
156
- }
157
-
158
- /**
159
- * Gets the template line where the error occurred.
160
- *
161
- * @return int The template line
162
- */
163
- public function getTemplateLine()
164
- {
165
- return $this->lineno;
166
- }
167
-
168
- /**
169
- * Sets the template line where the error occurred.
170
- *
171
- * @param int $lineno The template line
172
- */
173
- public function setTemplateLine($lineno)
174
- {
175
- $this->lineno = $lineno;
176
-
177
- $this->updateRepr();
178
- }
179
-
180
- /**
181
- * Gets the source context of the Twig template where the error occurred.
182
- *
183
- * @return Twig_Source|null
184
- */
185
- public function getSourceContext()
186
  {
187
- return $this->filename ? new Twig_Source($this->sourceCode, $this->filename, $this->sourcePath) : null;
188
- }
189
-
190
- /**
191
- * Sets the source context of the Twig template where the error occurred.
192
- */
193
- public function setSourceContext(Twig_Source $source = null)
194
- {
195
- if (null === $source) {
196
- $this->sourceCode = $this->filename = $this->sourcePath = null;
197
- } else {
198
- $this->sourceCode = $source->getCode();
199
- $this->filename = $source->getName();
200
- $this->sourcePath = $source->getPath();
201
- }
202
-
203
- $this->updateRepr();
204
- }
205
-
206
- public function guess()
207
- {
208
- $this->guessTemplateInfo();
209
- $this->updateRepr();
210
- }
211
-
212
- public function appendMessage($rawMessage)
213
- {
214
- $this->rawMessage .= $rawMessage;
215
- $this->updateRepr();
216
- }
217
-
218
- /**
219
- * @internal
220
- */
221
- protected function updateRepr()
222
- {
223
- $this->message = $this->rawMessage;
224
-
225
- if ($this->sourcePath && $this->lineno > 0) {
226
- $this->file = $this->sourcePath;
227
- $this->line = $this->lineno;
228
-
229
- return;
230
- }
231
-
232
- $dot = false;
233
- if ('.' === substr($this->message, -1)) {
234
- $this->message = substr($this->message, 0, -1);
235
- $dot = true;
236
- }
237
-
238
- $questionMark = false;
239
- if ('?' === substr($this->message, -1)) {
240
- $this->message = substr($this->message, 0, -1);
241
- $questionMark = true;
242
- }
243
-
244
- if ($this->filename) {
245
- if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) {
246
- $name = sprintf('"%s"', $this->filename);
247
- } else {
248
- $name = json_encode($this->filename);
249
- }
250
- $this->message .= sprintf(' in %s', $name);
251
- }
252
-
253
- if ($this->lineno && $this->lineno >= 0) {
254
- $this->message .= sprintf(' at line %d', $this->lineno);
255
- }
256
-
257
- if ($dot) {
258
- $this->message .= '.';
259
- }
260
-
261
- if ($questionMark) {
262
- $this->message .= '?';
263
- }
264
- }
265
-
266
- /**
267
- * @internal
268
- */
269
- protected function guessTemplateInfo()
270
- {
271
- $template = null;
272
- $templateClass = null;
273
-
274
- $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT);
275
- foreach ($backtrace as $trace) {
276
- if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) {
277
- $currentClass = get_class($trace['object']);
278
- $isEmbedContainer = 0 === strpos($templateClass, $currentClass);
279
- if (null === $this->filename || ($this->filename == $trace['object']->getTemplateName() && !$isEmbedContainer)) {
280
- $template = $trace['object'];
281
- $templateClass = get_class($trace['object']);
282
- }
283
- }
284
- }
285
-
286
- // update template name
287
- if (null !== $template && null === $this->filename) {
288
- $this->filename = $template->getTemplateName();
289
- }
290
-
291
- // update template path if any
292
- if (null !== $template && null === $this->sourcePath) {
293
- $src = $template->getSourceContext();
294
- $this->sourceCode = $src->getCode();
295
- $this->sourcePath = $src->getPath();
296
- }
297
-
298
- if (null === $template || $this->lineno > -1) {
299
- return;
300
- }
301
-
302
- $r = new ReflectionObject($template);
303
- $file = $r->getFileName();
304
-
305
- $exceptions = [$e = $this];
306
- while ($e instanceof self && $e = $e->getPrevious()) {
307
- $exceptions[] = $e;
308
- }
309
-
310
- while ($e = array_pop($exceptions)) {
311
- $traces = $e->getTrace();
312
- array_unshift($traces, ['file' => $e->getFile(), 'line' => $e->getLine()]);
313
-
314
- while ($trace = array_shift($traces)) {
315
- if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) {
316
- continue;
317
- }
318
-
319
- foreach ($template->getDebugInfo() as $codeLine => $templateLine) {
320
- if ($codeLine <= $trace['line']) {
321
- // update template line
322
- $this->lineno = $templateLine;
323
-
324
- return;
325
- }
326
- }
327
- }
328
- }
329
  }
330
  }
331
-
332
- class_alias('Twig_Error', 'Twig\Error\Error', false);
333
- class_exists('Twig_Source');
1
  <?php
2
 
3
+ use Twig\Error\Error;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Error\Error');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Error extends Error
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
 
src/lib/vendor/twig/twig/lib/Twig/Error/Loader.php CHANGED
@@ -1,36 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Exception thrown when an error occurs during template loading.
14
- *
15
- * Automatic template information guessing is always turned off as
16
- * if a template cannot be loaded, there is nothing to guess.
17
- * However, when a template is loaded from another one, then, we need
18
- * to find the current context and this is automatically done by
19
- * Twig_Template::displayWithErrorHandling().
20
- *
21
- * This strategy makes Twig_Environment::resolveTemplate() much faster.
22
- *
23
- * @author Fabien Potencier <fabien@symfony.com>
24
- */
25
- class Twig_Error_Loader extends Twig_Error
26
- {
27
- public function __construct($message, $lineno = -1, $source = null, Exception $previous = null)
28
- {
29
- Exception::__construct('', 0, $previous);
30
 
31
- $this->appendMessage($message);
32
- $this->setTemplateLine(false);
 
33
  }
34
  }
35
-
36
- class_alias('Twig_Error_Loader', 'Twig\Error\LoaderError', false);
1
  <?php
2
 
3
+ use Twig\Error\LoaderError;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Error\LoaderError');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Error_Loader extends LoaderError
9
+ {
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Error/Runtime.php CHANGED
@@ -1,22 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Exception thrown when an error occurs at runtime.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- class Twig_Error_Runtime extends Twig_Error
19
- {
20
- }
21
 
22
- class_alias('Twig_Error_Runtime', 'Twig\Error\RuntimeError', false);
 
 
 
 
1
  <?php
2
 
3
+ use Twig\Error\RuntimeError;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Error\RuntimeError');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Error_Runtime extends RuntimeError
9
+ {
10
+ }
11
+ }
src/lib/vendor/twig/twig/lib/Twig/Error/Syntax.php CHANGED
@@ -1,55 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Exception thrown when a syntax error occurs during lexing or parsing of a template.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- class Twig_Error_Syntax extends Twig_Error
19
- {
20
- /**
21
- * Tweaks the error message to include suggestions.
22
- *
23
- * @param string $name The original name of the item that does not exist
24
- * @param array $items An array of possible items
25
- */
26
- public function addSuggestions($name, array $items)
27
- {
28
- if (!$alternatives = self::computeAlternatives($name, $items)) {
29
- return;
30
- }
31
-
32
- $this->appendMessage(sprintf(' Did you mean "%s"?', implode('", "', $alternatives)));
33
- }
34
 
35
- /**
36
- * @internal
37
- *
38
- * To be merged with the addSuggestions() method in 2.0.
39
- */
40
- public static function computeAlternatives($name, $items)
41
  {
42
- $alternatives = [];
43
- foreach ($items as $item) {
44
- $lev = levenshtein($name, $item);
45
- if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
46
- $alternatives[$item] = $lev;
47
- }
48
- }
49
- asort($alternatives);
50
-
51
- return array_keys($alternatives);
52
  }
53
  }
54
-
55
- class_alias('Twig_Error_Syntax', 'Twig\Error\SyntaxError', false);
1
  <?php
2
 
3
+ use Twig\Error\SyntaxError;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Error\SyntaxError');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Error_Syntax extends SyntaxError
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/ExistsLoaderInterface.php CHANGED
@@ -1,31 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Adds an exists() method for loaders.
14
- *
15
- * @author Florin Patan <florinpatan@gmail.com>
16
- *
17
- * @deprecated since 1.12 (to be removed in 3.0)
18
- */
19
- interface Twig_ExistsLoaderInterface
20
- {
21
- /**
22
- * Check if we have the source code of a template, given its name.
23
- *
24
- * @param string $name The name of the template to check if we can load
25
- *
26
- * @return bool If the template source code is handled by this loader or not
27
- */
28
- public function exists($name);
29
- }
30
 
31
- class_alias('Twig_ExistsLoaderInterface', 'Twig\Loader\ExistsLoaderInterface', false);
 
 
 
 
1
  <?php
2
 
3
+ use Twig\Loader\ExistsLoaderInterface;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Loader\ExistsLoaderInterface');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_ExistsLoaderInterface extends ExistsLoaderInterface
9
+ {
10
+ }
11
+ }
src/lib/vendor/twig/twig/lib/Twig/ExpressionParser.php CHANGED
@@ -1,744 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Parses expressions.
15
- *
16
- * This parser implements a "Precedence climbing" algorithm.
17
- *
18
- * @see https://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
19
- * @see https://en.wikipedia.org/wiki/Operator-precedence_parser
20
- *
21
- * @author Fabien Potencier <fabien@symfony.com>
22
- *
23
- * @internal
24
- */
25
- class Twig_ExpressionParser
26
- {
27
- const OPERATOR_LEFT = 1;
28
- const OPERATOR_RIGHT = 2;
29
 
30
- protected $parser;
31
- protected $unaryOperators;
32
- protected $binaryOperators;
33
-
34
- private $env;
35
-
36
- public function __construct(Twig_Parser $parser, $env = null)
37
- {
38
- $this->parser = $parser;
39
-
40
- if ($env instanceof Twig_Environment) {
41
- $this->env = $env;
42
- $this->unaryOperators = $env->getUnaryOperators();
43
- $this->binaryOperators = $env->getBinaryOperators();
44
- } else {
45
- @trigger_error('Passing the operators as constructor arguments to '.__METHOD__.' is deprecated since version 1.27. Pass the environment instead.', E_USER_DEPRECATED);
46
-
47
- $this->env = $parser->getEnvironment();
48
- $this->unaryOperators = func_get_arg(1);
49
- $this->binaryOperators = func_get_arg(2);
50
- }
51
- }
52
-
53
- public function parseExpression($precedence = 0)
54
- {
55
- $expr = $this->getPrimary();
56
- $token = $this->parser->getCurrentToken();
57
- while ($this->isBinary($token) && $this->binaryOperators[$token->getValue()]['precedence'] >= $precedence) {
58
- $op = $this->binaryOperators[$token->getValue()];
59
- $this->parser->getStream()->next();
60
-
61
- if ('is not' === $token->getValue()) {
62
- $expr = $this->parseNotTestExpression($expr);
63
- } elseif ('is' === $token->getValue()) {
64
- $expr = $this->parseTestExpression($expr);
65
- } elseif (isset($op['callable'])) {
66
- $expr = call_user_func($op['callable'], $this->parser, $expr);
67
- } else {
68
- $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']);
69
- $class = $op['class'];
70
- $expr = new $class($expr, $expr1, $token->getLine());
71
- }
72
-
73
- $token = $this->parser->getCurrentToken();
74
- }
75
-
76
- if (0 === $precedence) {
77
- return $this->parseConditionalExpression($expr);
78
- }
79
-
80
- return $expr;
81
- }
82
-
83
- protected function getPrimary()
84
- {
85
- $token = $this->parser->getCurrentToken();
86
-
87
- if ($this->isUnary($token)) {
88
- $operator = $this->unaryOperators[$token->getValue()];
89
- $this->parser->getStream()->next();
90
- $expr = $this->parseExpression($operator['precedence']);
91
- $class = $operator['class'];
92
-
93
- return $this->parsePostfixExpression(new $class($expr, $token->getLine()));
94
- } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
95
- $this->parser->getStream()->next();
96
- $expr = $this->parseExpression();
97
- $this->parser->getStream()->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed');
98
-
99
- return $this->parsePostfixExpression($expr);
100
- }
101
-
102
- return $this->parsePrimaryExpression();
103
- }
104
-
105
- protected function parseConditionalExpression($expr)
106
- {
107
- while ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, '?')) {
108
- if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) {
109
- $expr2 = $this->parseExpression();
110
- if ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) {
111
- $expr3 = $this->parseExpression();
112
- } else {
113
- $expr3 = new Twig_Node_Expression_Constant('', $this->parser->getCurrentToken()->getLine());
114
- }
115
- } else {
116
- $expr2 = $expr;
117
- $expr3 = $this->parseExpression();
118
- }
119
-
120
- $expr = new Twig_Node_Expression_Conditional($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine());
121
- }
122
-
123
- return $expr;
124
- }
125
-
126
- protected function isUnary(Twig_Token $token)
127
- {
128
- return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]);
129
- }
130
-
131
- protected function isBinary(Twig_Token $token)
132
- {
133
- return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]);
134
- }
135
-
136
- public function parsePrimaryExpression()
137
- {
138
- $token = $this->parser->getCurrentToken();
139
- switch ($token->getType()) {
140
- case Twig_Token::NAME_TYPE:
141
- $this->parser->getStream()->next();
142
- switch ($token->getValue()) {
143
- case 'true':
144
- case 'TRUE':
145
- $node = new Twig_Node_Expression_Constant(true, $token->getLine());
146
- break;
147
-
148
- case 'false':
149
- case 'FALSE':
150
- $node = new Twig_Node_Expression_Constant(false, $token->getLine());
151
- break;
152
-
153
- case 'none':
154
- case 'NONE':
155
- case 'null':
156
- case 'NULL':
157
- $node = new Twig_Node_Expression_Constant(null, $token->getLine());
158
- break;
159
-
160
- default:
161
- if ('(' === $this->parser->getCurrentToken()->getValue()) {
162
- $node = $this->getFunctionNode($token->getValue(), $token->getLine());
163
- } else {
164
- $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine());
165
- }
166
- }
167
- break;
168
-
169
- case Twig_Token::NUMBER_TYPE:
170
- $this->parser->getStream()->next();
171
- $node = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
172
- break;
173
-
174
- case Twig_Token::STRING_TYPE:
175
- case Twig_Token::INTERPOLATION_START_TYPE:
176
- $node = $this->parseStringExpression();
177
- break;
178
-
179
- case Twig_Token::OPERATOR_TYPE:
180
- if (preg_match(Twig_Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) {
181
- // in this context, string operators are variable names
182
- $this->parser->getStream()->next();
183
- $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine());
184
- break;
185
- } elseif (isset($this->unaryOperators[$token->getValue()])) {
186
- $class = $this->unaryOperators[$token->getValue()]['class'];
187
-
188
- $ref = new ReflectionClass($class);
189
- $negClass = 'Twig_Node_Expression_Unary_Neg';
190
- $posClass = 'Twig_Node_Expression_Unary_Pos';
191
- if (!(in_array($ref->getName(), [$negClass, $posClass]) || $ref->isSubclassOf($negClass) || $ref->isSubclassOf($posClass))) {
192
- throw new Twig_Error_Syntax(sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext());
193
- }
194
-
195
- $this->parser->getStream()->next();
196
- $expr = $this->parsePrimaryExpression();
197
-
198
- $node = new $class($expr, $token->getLine());
199
- break;
200
- }
201
-
202
- // no break
203
- default:
204
- if ($token->test(Twig_Token::PUNCTUATION_TYPE, '[')) {
205
- $node = $this->parseArrayExpression();
206
- } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) {
207
- $node = $this->parseHashExpression();
208
- } elseif ($token->test(Twig_Token::OPERATOR_TYPE, '=') && ('==' === $this->parser->getStream()->look(-1)->getValue() || '!=' === $this->parser->getStream()->look(-1)->getValue())) {
209
- throw new Twig_Error_Syntax(sprintf('Unexpected operator of value "%s". Did you try to use "===" or "!==" for strict comparison? Use "is same as(value)" instead.', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext());
210
- } else {
211
- throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s".', Twig_Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext());
212
- }
213
- }
214
-
215
- return $this->parsePostfixExpression($node);
216
- }
217
-
218
- public function parseStringExpression()
219
- {
220
- $stream = $this->parser->getStream();
221
-
222
- $nodes = [];
223
- // a string cannot be followed by another string in a single expression
224
- $nextCanBeString = true;
225
- while (true) {
226
- if ($nextCanBeString && $token = $stream->nextIf(Twig_Token::STRING_TYPE)) {
227
- $nodes[] = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
228
- $nextCanBeString = false;
229
- } elseif ($stream->nextIf(Twig_Token::INTERPOLATION_START_TYPE)) {
230
- $nodes[] = $this->parseExpression();
231
- $stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
232
- $nextCanBeString = true;
233
- } else {
234
- break;
235
- }
236
- }
237
-
238
- $expr = array_shift($nodes);
239
- foreach ($nodes as $node) {
240
- $expr = new Twig_Node_Expression_Binary_Concat($expr, $node, $node->getTemplateLine());
241
- }
242
-
243
- return $expr;
244
- }
245
-
246
- public function parseArrayExpression()
247
- {
248
- $stream = $this->parser->getStream();
249
- $stream->expect(Twig_Token::PUNCTUATION_TYPE, '[', 'An array element was expected');
250
-
251
- $node = new Twig_Node_Expression_Array([], $stream->getCurrent()->getLine());
252
- $first = true;
253
- while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
254
- if (!$first) {
255
- $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma');
256
-
257
- // trailing ,?
258
- if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
259
- break;
260
- }
261
- }
262
- $first = false;
263
-
264
- $node->addElement($this->parseExpression());
265
- }
266
- $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed');
267
-
268
- return $node;
269
- }
270
-
271
- public function parseHashExpression()
272
- {
273
- $stream = $this->parser->getStream();
274
- $stream->expect(Twig_Token::PUNCTUATION_TYPE, '{', 'A hash element was expected');
275
-
276
- $node = new Twig_Node_Expression_Array([], $stream->getCurrent()->getLine());
277
- $first = true;
278
- while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) {
279
- if (!$first) {
280
- $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma');
281
-
282
- // trailing ,?
283
- if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) {
284
- break;
285
- }
286
- }
287
- $first = false;
288
-
289
- // a hash key can be:
290
- //
291
- // * a number -- 12
292
- // * a string -- 'a'
293
- // * a name, which is equivalent to a string -- a
294
- // * an expression, which must be enclosed in parentheses -- (1 + 2)
295
- if (($token = $stream->nextIf(Twig_Token::STRING_TYPE)) || ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) || $token = $stream->nextIf(Twig_Token::NUMBER_TYPE)) {
296
- $key = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
297
- } elseif ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
298
- $key = $this->parseExpression();
299
- } else {
300
- $current = $stream->getCurrent();
301
-
302
- throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s".', Twig_Token::typeToEnglish($current->getType()), $current->getValue()), $current->getLine(), $stream->getSourceContext());
303
- }
304
-
305
- $stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)');
306
- $value = $this->parseExpression();
307
-
308
- $node->addElement($value, $key);
309
- }
310
- $stream->expect(Twig_Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed');
311
-
312
- return $node;
313
- }
314
-
315
- public function parsePostfixExpression($node)
316
  {
317
- while (true) {
318
- $token = $this->parser->getCurrentToken();
319
- if (Twig_Token::PUNCTUATION_TYPE == $token->getType()) {
320
- if ('.' == $token->getValue() || '[' == $token->getValue()) {
321
- $node = $this->parseSubscriptExpression($node);
322
- } elseif ('|' == $token->getValue()) {
323
- $node = $this->parseFilterExpression($node);
324
- } else {
325
- break;
326
- }
327
- } else {
328
- break;
329
- }
330
- }
331
-
332
- return $node;
333
- }
334
-
335
- public function getFunctionNode($name, $line)
336
- {
337
- switch ($name) {
338
- case 'parent':
339
- $this->parseArguments();
340
- if (!count($this->parser->getBlockStack())) {
341
- throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden.', $line, $this->parser->getStream()->getSourceContext());
342
- }
343
-
344
- if (!$this->parser->getParent() && !$this->parser->hasTraits()) {
345
- throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden.', $line, $this->parser->getStream()->getSourceContext());
346
- }
347
-
348
- return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line);
349
- case 'block':
350
- $args = $this->parseArguments();
351
- if (count($args) < 1) {
352
- throw new Twig_Error_Syntax('The "block" function takes one argument (the block name).', $line, $this->parser->getStream()->getSourceContext());
353
- }
354
-
355
- return new Twig_Node_Expression_BlockReference($args->getNode(0), count($args) > 1 ? $args->getNode(1) : null, $line);
356
- case 'attribute':
357
- $args = $this->parseArguments();
358
- if (count($args) < 2) {
359
- throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes).', $line, $this->parser->getStream()->getSourceContext());
360
- }
361
-
362
- return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : null, Twig_Template::ANY_CALL, $line);
363
- default:
364
- if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) {
365
- $arguments = new Twig_Node_Expression_Array([], $line);
366
- foreach ($this->parseArguments() as $n) {
367
- $arguments->addElement($n);
368
- }
369
-
370
- $node = new Twig_Node_Expression_MethodCall($alias['node'], $alias['name'], $arguments, $line);
371
- $node->setAttribute('safe', true);
372
-
373
- return $node;
374
- }
375
-
376
- $args = $this->parseArguments(true);
377
- $class = $this->getFunctionNodeClass($name, $line);
378
-
379
- return new $class($name, $args, $line);
380
- }
381
- }
382
-
383
- public function parseSubscriptExpression($node)
384
- {
385
- $stream = $this->parser->getStream();
386
- $token = $stream->next();
387
- $lineno = $token->getLine();
388
- $arguments = new Twig_Node_Expression_Array([], $lineno);
389
- $type = Twig_Template::ANY_CALL;
390
- if ('.' == $token->getValue()) {
391
- $token = $stream->next();
392
- if (
393
- Twig_Token::NAME_TYPE == $token->getType()
394
- ||
395
- Twig_Token::NUMBER_TYPE == $token->getType()
396
- ||
397
- (Twig_Token::OPERATOR_TYPE == $token->getType() && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue()))
398
- ) {
399
- $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno);
400
-
401
- if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
402
- $type = Twig_Template::METHOD_CALL;
403
- foreach ($this->parseArguments() as $n) {
404
- $arguments->addElement($n);
405
- }
406
- }
407
- } else {
408
- throw new Twig_Error_Syntax('Expected name or number.', $lineno, $stream->getSourceContext());
409
- }
410
-
411
- if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
412
- if (!$arg instanceof Twig_Node_Expression_Constant) {
413
- throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s").', $node->getAttribute('name')), $token->getLine(), $stream->getSourceContext());
414
- }
415
-
416
- $name = $arg->getAttribute('value');
417
-
418
- if ($this->parser->isReservedMacroName($name)) {
419
- throw new Twig_Error_Syntax(sprintf('"%s" cannot be called as macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext());
420
- }
421
-
422
- $node = new Twig_Node_Expression_MethodCall($node, 'get'.$name, $arguments, $lineno);
423
- $node->setAttribute('safe', true);
424
-
425
- return $node;
426
- }
427
- } else {
428
- $type = Twig_Template::ARRAY_CALL;
429
-
430
- // slice?
431
- $slice = false;
432
- if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
433
- $slice = true;
434
- $arg = new Twig_Node_Expression_Constant(0, $token->getLine());
435
- } else {
436
- $arg = $this->parseExpression();
437
- }
438
-
439
- if ($stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) {
440
- $slice = true;
441
- }
442
-
443
- if ($slice) {
444
- if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
445
- $length = new Twig_Node_Expression_Constant(null, $token->getLine());
446
- } else {
447
- $length = $this->parseExpression();
448
- }
449
-
450
- $class = $this->getFilterNodeClass('slice', $token->getLine());
451
- $arguments = new Twig_Node([$arg, $length]);
452
- $filter = new $class($node, new Twig_Node_Expression_Constant('slice', $token->getLine()), $arguments, $token->getLine());
453
-
454
- $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']');
455
-
456
- return $filter;
457
- }
458
-
459
- $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']');
460
- }
461
-
462
- return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno);
463
- }
464
-
465
- public function parseFilterExpression($node)
466
- {
467
- $this->parser->getStream()->next();
468
-
469
- return $this->parseFilterExpressionRaw($node);
470
- }
471
-
472
- public function parseFilterExpressionRaw($node, $tag = null)
473
- {
474
- while (true) {
475
- $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE);
476
-
477
- $name = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine());
478
- if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
479
- $arguments = new Twig_Node();
480
- } else {
481
- $arguments = $this->parseArguments(true);
482
- }
483
-
484
- $class = $this->getFilterNodeClass($name->getAttribute('value'), $token->getLine());
485
-
486
- $node = new $class($node, $name, $arguments, $token->getLine(), $tag);
487
-
488
- if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '|')) {
489
- break;
490
- }
491
-
492
- $this->parser->getStream()->next();
493
- }
494
-
495
- return $node;
496
- }
497
-
498
- /**
499
- * Parses arguments.
500
- *
501
- * @param bool $namedArguments Whether to allow named arguments or not
502
- * @param bool $definition Whether we are parsing arguments for a function definition
503
- *
504
- * @return Twig_Node
505
- *
506
- * @throws Twig_Error_Syntax
507
- */
508
- public function parseArguments($namedArguments = false, $definition = false)
509
- {
510
- $args = [];
511
- $stream = $this->parser->getStream();
512
-
513
- $stream->expect(Twig_Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis');
514
- while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ')')) {
515
- if (!empty($args)) {
516
- $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma');
517
- }
518
-
519
- if ($definition) {
520
- $token = $stream->expect(Twig_Token::NAME_TYPE, null, 'An argument must be a name');
521
- $value = new Twig_Node_Expression_Name($token->getValue(), $this->parser->getCurrentToken()->getLine());
522
- } else {
523
- $value = $this->parseExpression();
524
- }
525
-
526
- $name = null;
527
- if ($namedArguments && $token = $stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) {
528
- if (!$value instanceof Twig_Node_Expression_Name) {
529
- throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given.', get_class($value)), $token->getLine(), $stream->getSourceContext());
530
- }
531
- $name = $value->getAttribute('name');
532
-
533
- if ($definition) {
534
- $value = $this->parsePrimaryExpression();
535
-
536
- if (!$this->checkConstantExpression($value)) {
537
- throw new Twig_Error_Syntax(sprintf('A default value for an argument must be a constant (a boolean, a string, a number, or an array).'), $token->getLine(), $stream->getSourceContext());
538
- }
539
- } else {
540
- $value = $this->parseExpression();
541
- }
542
- }
543
-
544
- if ($definition) {
545
- if (null === $name) {
546
- $name = $value->getAttribute('name');
547
- $value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine());
548
- }
549
- $args[$name] = $value;
550
- } else {
551
- if (null === $name) {
552
- $args[] = $value;
553
- } else {
554
- $args[$name] = $value;
555
- }
556
- }
557
- }
558
- $stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis');
559
-
560
- return new Twig_Node($args);
561
- }
562
-
563
- public function parseAssignmentExpression()
564
- {
565
- $stream = $this->parser->getStream();
566
- $targets = [];
567
- while (true) {
568
- $token = $stream->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to');
569
- $value = $token->getValue();
570
- if (in_array(strtolower($value), ['true', 'false', 'none', 'null'])) {
571
- throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s".', $value), $token->getLine(), $stream->getSourceContext());
572
- }
573
- $targets[] = new Twig_Node_Expression_AssignName($value, $token->getLine());
574
-
575
- if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) {
576
- break;
577
- }
578
- }
579
-
580
- return new Twig_Node($targets);
581
- }
582
-
583
- public function parseMultitargetExpression()
584
- {
585
- $targets = [];
586
- while (true) {
587
- $targets[] = $this->parseExpression();
588
- if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) {
589
- break;
590
- }
591
- }
592
-
593
- return new Twig_Node($targets);
594
- }
595
-
596
- private function parseNotTestExpression(Twig_NodeInterface $node)
597
- {
598
- return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($node), $this->parser->getCurrentToken()->getLine());
599
- }
600
-
601
- private function parseTestExpression(Twig_NodeInterface $node)
602
- {
603
- $stream = $this->parser->getStream();
604
- list($name, $test) = $this->getTest($node->getTemplateLine());
605
-
606
- $class = $this->getTestNodeClass($test);
607
- $arguments = null;
608
- if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
609
- $arguments = $this->parser->getExpressionParser()->parseArguments(true);
610
- }
611
-
612
- return new $class($node, $name, $arguments, $this->parser->getCurrentToken()->getLine());
613
- }
614
-
615
- private function getTest($line)
616
- {
617
- $stream = $this->parser->getStream();
618
- $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
619
-
620
- if ($test = $this->env->getTest($name)) {
621
- return [$name, $test];
622
- }
623
-
624
- if ($stream->test(Twig_Token::NAME_TYPE)) {
625
- // try 2-words tests
626
- $name = $name.' '.$this->parser->getCurrentToken()->getValue();
627
-
628
- if ($test = $this->env->getTest($name)) {
629
- $stream->next();
630
-
631
- return [$name, $test];
632
- }
633
- }
634
-
635
- $e = new Twig_Error_Syntax(sprintf('Unknown "%s" test.', $name), $line, $stream->getSourceContext());
636
- $e->addSuggestions($name, array_keys($this->env->getTests()));
637
-
638
- throw $e;
639
- }
640
-
641
- private function getTestNodeClass($test)
642
- {
643
- if ($test instanceof Twig_SimpleTest && $test->isDeprecated()) {
644
- $stream = $this->parser->getStream();
645
- $message = sprintf('Twig Test "%s" is deprecated', $test->getName());
646
- if (!is_bool($test->getDeprecatedVersion())) {
647
- $message .= sprintf(' since version %s', $test->getDeprecatedVersion());
648
- }
649
- if ($test->getAlternative()) {
650
- $message .= sprintf('. Use "%s" instead', $test->getAlternative());
651
- }
652
- $src = $stream->getSourceContext();
653
- $message .= sprintf(' in %s at line %d.', $src->getPath() ? $src->getPath() : $src->getName(), $stream->getCurrent()->getLine());
654
-
655
- @trigger_error($message, E_USER_DEPRECATED);
656
- }
657
-
658
- if ($test instanceof Twig_SimpleTest) {
659
- return $test->getNodeClass();
660
- }
661
-
662
- return $test instanceof Twig_Test_Node ? $test->getClass() : 'Twig_Node_Expression_Test';
663
- }
664
-
665
- protected function getFunctionNodeClass($name, $line)
666
- {
667
- if (false === $function = $this->env->getFunction($name)) {
668
- $e = new Twig_Error_Syntax(sprintf('Unknown "%s" function.', $name), $line, $this->parser->getStream()->getSourceContext());
669
- $e->addSuggestions($name, array_keys($this->env->getFunctions()));
670
-
671
- throw $e;
672
- }
673
-
674
- if ($function instanceof Twig_SimpleFunction && $function->isDeprecated()) {
675
- $message = sprintf('Twig Function "%s" is deprecated', $function->getName());
676
- if (!is_bool($function->getDeprecatedVersion())) {
677
- $message .= sprintf(' since version %s', $function->getDeprecatedVersion());
678
- }
679
- if ($function->getAlternative()) {
680
- $message .= sprintf('. Use "%s" instead', $function->getAlternative());
681
- }
682
- $src = $this->parser->getStream()->getSourceContext();
683
- $message .= sprintf(' in %s at line %d.', $src->getPath() ? $src->getPath() : $src->getName(), $line);
684
-
685
- @trigger_error($message, E_USER_DEPRECATED);
686
- }
687
-
688
- if ($function instanceof Twig_SimpleFunction) {
689
- return $function->getNodeClass();
690
- }
691
-
692
- return $function instanceof Twig_Function_Node ? $function->getClass() : 'Twig_Node_Expression_Function';
693
- }
694
-
695
- protected function getFilterNodeClass($name, $line)
696
- {
697
- if (false === $filter = $this->env->getFilter($name)) {
698
- $e = new Twig_Error_Syntax(sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getStream()->getSourceContext());
699
- $e->addSuggestions($name, array_keys($this->env->getFilters()));
700
-
701
- throw $e;
702
- }
703
-
704
- if ($filter instanceof Twig_SimpleFilter && $filter->isDeprecated()) {
705
- $message = sprintf('Twig Filter "%s" is deprecated', $filter->getName());
706
- if (!is_bool($filter->getDeprecatedVersion())) {
707
- $message .= sprintf(' since version %s', $filter->getDeprecatedVersion());
708
- }
709
- if ($filter->getAlternative()) {
710
- $message .= sprintf('. Use "%s" instead', $filter->getAlternative());
711
- }
712
- $src = $this->parser->getStream()->getSourceContext();
713
- $message .= sprintf(' in %s at line %d.', $src->getPath() ? $src->getPath() : $src->getName(), $line);
714
-
715
- @trigger_error($message, E_USER_DEPRECATED);
716
- }
717
-
718
- if ($filter instanceof Twig_SimpleFilter) {
719
- return $filter->getNodeClass();
720
- }
721
-
722
- return $filter instanceof Twig_Filter_Node ? $filter->getClass() : 'Twig_Node_Expression_Filter';
723
- }
724
-
725
- // checks that the node only contains "constant" elements
726
- protected function checkConstantExpression(Twig_NodeInterface $node)
727
- {
728
- if (!($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array
729
- || $node instanceof Twig_Node_Expression_Unary_Neg || $node instanceof Twig_Node_Expression_Unary_Pos
730
- )) {
731
- return false;
732
- }
733
-
734
- foreach ($node as $n) {
735
- if (!$this->checkConstantExpression($n)) {
736
- return false;
737
- }
738
- }
739
-
740
- return true;
741
  }
742
  }
743
-
744
- class_alias('Twig_ExpressionParser', 'Twig\ExpressionParser', false);
1
  <?php
2
 
3
+ use Twig\ExpressionParser;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\ExpressionParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_ExpressionParser extends ExpressionParser
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Extension.php CHANGED
@@ -1,69 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- abstract class Twig_Extension implements Twig_ExtensionInterface
13
- {
14
- /**
15
- * @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead
16
- */
17
- public function initRuntime(Twig_Environment $environment)
18
- {
19
- }
20
-
21
- public function getTokenParsers()
22
- {
23
- return [];
24
- }
25
-
26
- public function getNodeVisitors()
27
- {
28
- return [];
29
- }
30
-
31
- public function getFilters()
32
- {
33
- return [];
34
- }
35
-
36
- public function getTests()
37
- {
38
- return [];
39
- }
40
-
41
- public function getFunctions()
42
- {
43
- return [];
44
- }
45
-
46
- public function getOperators()
47
- {
48
- return [];
49
- }
50
-
51
- /**
52
- * @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_GlobalsInterface instead
53
- */
54
- public function getGlobals()
55
- {
56
- return [];
57
- }
58
 
59
- /**
60
- * @deprecated since 1.26 (to be removed in 2.0), not used anymore internally
61
- */
62
- public function getName()
63
  {
64
- return get_class($this);
65
  }
66
  }
67
-
68
- class_alias('Twig_Extension', 'Twig\Extension\AbstractExtension', false);
69
- class_exists('Twig_Environment');
1
  <?php
2
 
3
+ use Twig\Extension\AbstractExtension;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Extension\AbstractExtension');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Extension extends AbstractExtension
 
 
9
  {
 
10
  }
11
  }
 
 
 
src/lib/vendor/twig/twig/lib/Twig/Extension/Core.php CHANGED
@@ -1,1647 +1,11 @@
1
  <?php
2
 
3
- if (!defined('ENT_SUBSTITUTE')) {
4
- define('ENT_SUBSTITUTE', 8);
5
- }
6
-
7
- /*
8
- * This file is part of Twig.
9
- *
10
- * (c) Fabien Potencier
11
- *
12
- * For the full copyright and license information, please view the LICENSE
13
- * file that was distributed with this source code.
14
- */
15
-
16
- /**
17
- * @final
18
- */
19
- class Twig_Extension_Core extends Twig_Extension
20
- {
21
- protected $dateFormats = ['F j, Y H:i', '%d days'];
22
- protected $numberFormat = [0, '.', ','];
23
- protected $timezone = null;
24
- protected $escapers = [];
25
-
26
- /**
27
- * Defines a new escaper to be used via the escape filter.
28
- *
29
- * @param string $strategy The strategy name that should be used as a strategy in the escape call
30
- * @param callable $callable A valid PHP callable
31
- */
32
- public function setEscaper($strategy, $callable)
33
- {
34
- $this->escapers[$strategy] = $callable;
35
- }
36
-
37
- /**
38
- * Gets all defined escapers.
39
- *
40
- * @return array An array of escapers
41
- */
42
- public function getEscapers()
43
- {
44
- return $this->escapers;
45
- }
46
-
47
- /**
48
- * Sets the default format to be used by the date filter.
49
- *
50
- * @param string $format The default date format string
51
- * @param string $dateIntervalFormat The default date interval format string
52
- */
53
- public function setDateFormat($format = null, $dateIntervalFormat = null)
54
- {
55
- if (null !== $format) {
56
- $this->dateFormats[0] = $format;
57
- }
58
-
59
- if (null !== $dateIntervalFormat) {
60
- $this->dateFormats[1] = $dateIntervalFormat;
61
- }
62
- }
63
-
64
- /**
65
- * Gets the default format to be used by the date filter.
66
- *
67
- * @return array The default date format string and the default date interval format string
68
- */
69
- public function getDateFormat()
70
- {
71
- return $this->dateFormats;
72
- }
73
-
74
- /**
75
- * Sets the default timezone to be used by the date filter.
76
- *
77
- * @param DateTimeZone|string $timezone The default timezone string or a DateTimeZone object
78
- */
79
- public function setTimezone($timezone)
80
- {
81
- $this->timezone = $timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone);
82
- }
83
-
84
- /**
85
- * Gets the default timezone to be used by the date filter.
86
- *
87
- * @return DateTimeZone The default timezone currently in use
88
- */
89
- public function getTimezone()
90
- {
91
- if (null === $this->timezone) {
92
- $this->timezone = new DateTimeZone(date_default_timezone_get());
93
- }
94
-
95
- return $this->timezone;
96
- }
97
-
98
- /**
99
- * Sets the default format to be used by the number_format filter.
100
- *
101
- * @param int $decimal the number of decimal places to use
102
- * @param string $decimalPoint the character(s) to use for the decimal point
103
- * @param string $thousandSep the character(s) to use for the thousands separator
104
- */
105
- public function setNumberFormat($decimal, $decimalPoint, $thousandSep)
106
- {
107
- $this->numberFormat = [$decimal, $decimalPoint, $thousandSep];
108
- }
109
-
110
- /**
111
- * Get the default format used by the number_format filter.
112
- *
113
- * @return array The arguments for number_format()
114
- */
115
- public function getNumberFormat()
116
- {
117
- return $this->numberFormat;
118
- }
119
-
120
- public function getTokenParsers()
121
- {
122
- return [
123
- new Twig_TokenParser_For(),
124
- new Twig_TokenParser_If(),
125
- new Twig_TokenParser_Extends(),
126
- new Twig_TokenParser_Include(),
127
- new Twig_TokenParser_Block(),
128
- new Twig_TokenParser_Use(),
129
- new Twig_TokenParser_Filter(),
130
- new Twig_TokenParser_Macro(),
131
- new Twig_TokenParser_Import(),
132
- new Twig_TokenParser_From(),
133
- new Twig_TokenParser_Set(),
134
- new Twig_TokenParser_Spaceless(),
135
- new Twig_TokenParser_Flush(),
136
- new Twig_TokenParser_Do(),
137
- new Twig_TokenParser_Embed(),
138
- new Twig_TokenParser_With(),
139
- new Twig_TokenParser_Deprecated(),
140
- ];
141
- }
142
-
143
- public function getFilters()
144
- {
145
- $filters = [
146
- // formatting filters
147
- new Twig_SimpleFilter('date', 'twig_date_format_filter', ['needs_environment' => true]),
148
- new Twig_SimpleFilter('date_modify', 'twig_date_modify_filter', ['needs_environment' => true]),
149
- new Twig_SimpleFilter('format', 'sprintf'),
150
- new Twig_SimpleFilter('replace', 'twig_replace_filter'),
151
- new Twig_SimpleFilter('number_format', 'twig_number_format_filter', ['needs_environment' => true]),
152
- new Twig_SimpleFilter('abs', 'abs'),
153
- new Twig_SimpleFilter('round', 'twig_round'),
154
-
155
- // encoding
156
- new Twig_SimpleFilter('url_encode', 'twig_urlencode_filter'),
157
- new Twig_SimpleFilter('json_encode', 'twig_jsonencode_filter'),
158
- new Twig_SimpleFilter('convert_encoding', 'twig_convert_encoding'),
159
-
160
- // string filters
161
- new Twig_SimpleFilter('title', 'twig_title_string_filter', ['needs_environment' => true]),
162
- new Twig_SimpleFilter('capitalize', 'twig_capitalize_string_filter', ['needs_environment' => true]),
163
- new Twig_SimpleFilter('upper', 'strtoupper'),
164
- new Twig_SimpleFilter('lower', 'strtolower'),
165
- new Twig_SimpleFilter('striptags', 'strip_tags'),
166
- new Twig_SimpleFilter('trim', 'twig_trim_filter'),
167
- new Twig_SimpleFilter('nl2br', 'nl2br', ['pre_escape' => 'html', 'is_safe' => ['html']]),
168
-
169
- // array helpers
170
- new Twig_SimpleFilter('join', 'twig_join_filter'),
171
- new Twig_SimpleFilter('split', 'twig_split_filter', ['needs_environment' => true]),
172
- new Twig_SimpleFilter('sort', 'twig_sort_filter'),
173
- new Twig_SimpleFilter('merge', 'twig_array_merge'),
174
- new Twig_SimpleFilter('batch', 'twig_array_batch'),
175
-
176
- // string/array filters
177
- new Twig_SimpleFilter('reverse', 'twig_reverse_filter', ['needs_environment' => true]),
178
- new Twig_SimpleFilter('length', 'twig_length_filter', ['needs_environment' => true]),
179
- new Twig_SimpleFilter('slice', 'twig_slice', ['needs_environment' => true]),
180
- new Twig_SimpleFilter('first', 'twig_first', ['needs_environment' => true]),
181
- new Twig_SimpleFilter('last', 'twig_last', ['needs_environment' => true]),
182
-
183
- // iteration and runtime
184
- new Twig_SimpleFilter('default', '_twig_default_filter', ['node_class' => 'Twig_Node_Expression_Filter_Default']),
185
- new Twig_SimpleFilter('keys', 'twig_get_array_keys_filter'),
186
-
187
- // escaping
188
- new Twig_SimpleFilter('escape', 'twig_escape_filter', ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']),
189
- new Twig_SimpleFilter('e', 'twig_escape_filter', ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']),
190
- ];
191
-
192
- if (function_exists('mb_get_info')) {
193
- $filters[] = new Twig_SimpleFilter('upper', 'twig_upper_filter', ['needs_environment' => true]);
194
- $filters[] = new Twig_SimpleFilter('lower', 'twig_lower_filter', ['needs_environment' => true]);
195
- }
196
-
197
- return $filters;
198
- }
199
-
200
- public function getFunctions()
201
- {
202
- return [
203
- new Twig_SimpleFunction('max', 'max'),
204
- new Twig_SimpleFunction('min', 'min'),
205
- new Twig_SimpleFunction('range', 'range'),
206
- new Twig_SimpleFunction('constant', 'twig_constant'),
207
- new Twig_SimpleFunction('cycle', 'twig_cycle'),
208
- new Twig_SimpleFunction('random', 'twig_random', ['needs_environment' => true]),
209
- new Twig_SimpleFunction('date', 'twig_date_converter', ['needs_environment' => true]),
210
- new Twig_SimpleFunction('include', 'twig_include', ['needs_environment' => true, 'needs_context' => true, 'is_safe' => ['all']]),
211
- new Twig_SimpleFunction('source', 'twig_source', ['needs_environment' => true, 'is_safe' => ['all']]),
212
- ];
213
- }
214
-
215
- public function getTests()
216
- {
217
- return [
218
- new Twig_SimpleTest('even', null, ['node_class' => 'Twig_Node_Expression_Test_Even']),
219
- new Twig_SimpleTest('odd', null, ['node_class' => 'Twig_Node_Expression_Test_Odd']),
220
- new Twig_SimpleTest('defined', null, ['node_class' => 'Twig_Node_Expression_Test_Defined']),
221
- new Twig_SimpleTest('sameas', null, ['node_class' => 'Twig_Node_Expression_Test_Sameas', 'deprecated' => '1.21', 'alternative' => 'same as']),
222
- new Twig_SimpleTest('same as', null, ['node_class' => 'Twig_Node_Expression_Test_Sameas']),
223
- new Twig_SimpleTest('none', null, ['node_class' => 'Twig_Node_Expression_Test_Null']),
224
- new Twig_SimpleTest('null', null, ['node_class' => 'Twig_Node_Expression_Test_Null']),
225
- new Twig_SimpleTest('divisibleby', null, ['node_class' => 'Twig_Node_Expression_Test_Divisibleby', 'deprecated' => '1.21', 'alternative' => 'divisible by']),
226
- new Twig_SimpleTest('divisible by', null, ['node_class' => 'Twig_Node_Expression_Test_Divisibleby']),
227
- new Twig_SimpleTest('constant', null, ['node_class' => 'Twig_Node_Expression_Test_Constant']),
228
- new Twig_SimpleTest('empty', 'twig_test_empty'),
229
- new Twig_SimpleTest('iterable', 'twig_test_iterable'),
230
- ];
231
- }
232
-
233
- public function getOperators()
234
- {
235
- return [
236
- [
237
- 'not' => ['precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'],
238
- '-' => ['precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Neg'],
239
- '+' => ['precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Pos'],
240
- ],
241
- [
242
- 'or' => ['precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
243
- 'and' => ['precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
244
- 'b-or' => ['precedence' => 16, 'class' => 'Twig_Node_Expression_Binary_BitwiseOr', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
245
- 'b-xor' => ['precedence' => 17, 'class' => 'Twig_Node_Expression_Binary_BitwiseXor', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
246
- 'b-and' => ['precedence' => 18, 'class' => 'Twig_Node_Expression_Binary_BitwiseAnd', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
247
- '==' => ['precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
248
- '!=' => ['precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
249
- '<' => ['precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
250
- '>' => ['precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
251
- '>=' => ['precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
252
- '<=' => ['precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
253
- 'not in' => ['precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotIn', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
254
- 'in' => ['precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_In', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
255
- 'matches' => ['precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Matches', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
256
- 'starts with' => ['precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_StartsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
257
- 'ends with' => ['precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_EndsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
258
- '..' => ['precedence' => 25, 'class' => 'Twig_Node_Expression_Binary_Range', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
259
- '+' => ['precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Add', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
260
- '-' => ['precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Sub', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
261
- '~' => ['precedence' => 40, 'class' => 'Twig_Node_Expression_Binary_Concat', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
262
- '*' => ['precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mul', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
263
- '/' => ['precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Div', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
264
- '//' => ['precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_FloorDiv', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
265
- '%' => ['precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
266
- 'is' => ['precedence' => 100, 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
267
- 'is not' => ['precedence' => 100, 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT],
268
- '**' => ['precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT],
269
- '??' => ['precedence' => 300, 'class' => 'Twig_Node_Expression_NullCoalesce', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT],
270
- ],
271
- ];
272
- }
273
-
274
- public function getName()
275
- {
276
- return 'core';
277
- }
278
- }
279
-
280
- /**
281
- * Cycles over a value.
282
- *
283
- * @param ArrayAccess|array $values
284
- * @param int $position The cycle position
285
- *
286
- * @return string The next value in the cycle
287
- */
288
- function twig_cycle($values, $position)
289
- {
290
- if (!is_array($values) && !$values instanceof ArrayAccess) {
291
- return $values;
292
- }
293
-
294
- return $values[$position % count($values)];
295
- }
296
-
297
- /**
298
- * Returns a random value depending on the supplied parameter type:
299
- * - a random item from a Traversable or array
300
- * - a random character from a string
301
- * - a random integer between 0 and the integer parameter.
302
- *
303
- * @param Twig_Environment $env
304
- * @param Traversable|array|int|float|string $values The values to pick a random item from
305
- *
306
- * @throws Twig_Error_Runtime when $values is an empty array (does not apply to an empty string which is returned as is)
307
- *
308
- * @return mixed A random value from the given sequence
309
- */
310
- function twig_random(Twig_Environment $env, $values = null)
311
- {
312
- if (null === $values) {
313
- return mt_rand();
314
- }
315
-
316
- if (is_int($values) || is_float($values)) {
317
- return $values < 0 ? mt_rand($values, 0) : mt_rand(0, $values);
318
- }
319
-
320
- if ($values instanceof Traversable) {
321
- $values = iterator_to_array($values);
322
- } elseif (is_string($values)) {
323
- if ('' === $values) {
324
- return '';
325
- }
326
- if (null !== $charset = $env->getCharset()) {
327
- if ('UTF-8' !== $charset) {
328
- $values = twig_convert_encoding($values, 'UTF-8', $charset);
329
- }
330
-
331
- // unicode version of str_split()
332
- // split at all positions, but not after the start and not before the end
333
- $values = preg_split('/(?<!^)(?!$)/u', $values);
334
-
335
- if ('UTF-8' !== $charset) {
336
- foreach ($values as $i => $value) {
337
- $values[$i] = twig_convert_encoding($value, $charset, 'UTF-8');
338
- }
339
- }
340
- } else {
341
- return $values[mt_rand(0, strlen($values) - 1)];
342
- }
343
- }
344
-
345
- if (!is_array($values)) {
346
- return $values;
347
- }
348
-
349
- if (0 === count($values)) {
350
- throw new Twig_Error_Runtime('The random function cannot pick from an empty array.');
351
- }
352
-
353
- return $values[array_rand($values, 1)];
354
- }
355
-
356
- /**
357
- * Converts a date to the given format.
358
- *
359
- * <pre>
360
- * {{ post.published_at|date("m/d/Y") }}
361
- * </pre>
362
- *
363
- * @param Twig_Environment $env
364
- * @param DateTime|DateTimeInterface|DateInterval|string $date A date
365
- * @param string|null $format The target format, null to use the default
366
- * @param DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged
367
- *
368
- * @return string The formatted date
369
- */
370
- function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $timezone = null)
371
- {
372
- if (null === $format) {
373
- $formats = $env->getExtension('Twig_Extension_Core')->getDateFormat();
374
- $format = $date instanceof DateInterval ? $formats[1] : $formats[0];
375
- }
376
-
377
- if ($date instanceof DateInterval) {
378
- return $date->format($format);
379
- }
380
-
381
- return twig_date_converter($env, $date, $timezone)->format($format);
382
- }
383
-
384
- /**
385
- * Returns a new date object modified.
386
- *
387
- * <pre>
388
- * {{ post.published_at|date_modify("-1day")|date("m/d/Y") }}
389
- * </pre>
390
- *
391
- * @param Twig_Environment $env
392
- * @param DateTime|string $date A date
393
- * @param string $modifier A modifier string
394
- *
395
- * @return DateTime A new date object
396
- */
397
- function twig_date_modify_filter(Twig_Environment $env, $date, $modifier)
398
- {
399
- $date = twig_date_converter($env, $date, false);
400
- $resultDate = $date->modify($modifier);
401
-
402
- // This is a hack to ensure PHP 5.2 support and support for DateTimeImmutable
403
- // DateTime::modify does not return the modified DateTime object < 5.3.0
404
- // and DateTimeImmutable does not modify $date.
405
- return null === $resultDate ? $date : $resultDate;
406
- }
407
-
408
- /**
409
- * Converts an input to a DateTime instance.
410
- *
411
- * <pre>
412
- * {% if date(user.created_at) < date('+2days') %}
413
- * {# do something #}
414
- * {% endif %}
415
- * </pre>
416
- *
417
- * @param Twig_Environment $env
418
- * @param DateTime|DateTimeInterface|string|null $date A date
419
- * @param DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged
420
- *
421
- * @return DateTime A DateTime instance
422
- */
423
- function twig_date_converter(Twig_Environment $env, $date = null, $timezone = null)
424
- {
425
- // determine the timezone
426
- if (false !== $timezone) {
427
- if (null === $timezone) {
428
- $timezone = $env->getExtension('Twig_Extension_Core')->getTimezone();
429
- } elseif (!$timezone instanceof DateTimeZone) {
430
- $timezone = new DateTimeZone($timezone);
431
- }
432
- }
433
-
434
- // immutable dates
435
- if ($date instanceof DateTimeImmutable) {
436
- return false !== $timezone ? $date->setTimezone($timezone) : $date;
437
- }
438
-
439
- if ($date instanceof DateTime || $date instanceof DateTimeInterface) {
440
- $date = clone $date;
441
- if (false !== $timezone) {
442
- $date->setTimezone($timezone);
443
- }
444
-
445
- return $date;
446
- }
447
-
448
- if (null === $date || 'now' === $date) {
449
- return new DateTime($date, false !== $timezone ? $timezone : $env->getExtension('Twig_Extension_Core')->getTimezone());
450
- }
451
-
452
- $asString = (string) $date;
453
- if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) {
454
- $date = new DateTime('@'.$date);
455
- } else {
456
- $date = new DateTime($date, $env->getExtension('Twig_Extension_Core')->getTimezone());
457
- }
458
-
459
- if (false !== $timezone) {
460
- $date->setTimezone($timezone);
461
- }
462
-
463
- return $date;
464
- }
465
-
466
- /**
467
- * Replaces strings within a string.
468
- *
469
- * @param string $str String to replace in
470
- * @param array|Traversable $from Replace values
471
- * @param string|null $to Replace to, deprecated (@see https://secure.php.net/manual/en/function.strtr.php)
472
- *
473
- * @return string
474
- */
475
- function twig_replace_filter($str, $from, $to = null)
476
- {
477
- if ($from instanceof Traversable) {
478
- $from = iterator_to_array($from);
479
- } elseif (is_string($from) && is_string($to)) {
480
- @trigger_error('Using "replace" with character by character replacement is deprecated since version 1.22 and will be removed in Twig 2.0', E_USER_DEPRECATED);
481
-
482
- return strtr($str, $from, $to);
483
- } elseif (!is_array($from)) {
484
- throw new Twig_Error_Runtime(sprintf('The "replace" filter expects an array or "Traversable" as replace values, got "%s".', is_object($from) ? get_class($from) : gettype($from)));
485
- }
486
-
487
- return strtr($str, $from);
488
- }
489
-
490
- /**
491
- * Rounds a number.
492
- *
493
- * @param int|float $value The value to round
494
- * @param int|float $precision The rounding precision
495
- * @param string $method The method to use for rounding
496
- *
497
- * @return int|float The rounded number
498
- */
499
- function twig_round($value, $precision = 0, $method = 'common')
500
- {
501
- if ('common' == $method) {
502
- return round($value, $precision);
503
- }
504
-
505
- if ('ceil' != $method && 'floor' != $method) {
506
- throw new Twig_Error_Runtime('The round filter only supports the "common", "ceil", and "floor" methods.');
507
- }
508
-
509
- return $method($value * pow(10, $precision)) / pow(10, $precision);
510
- }
511
-
512
- /**
513
- * Number format filter.
514
- *
515
- * All of the formatting options can be left null, in that case the defaults will
516
- * be used. Supplying any of the parameters will override the defaults set in the
517
- * environment object.
518
- *
519
- * @param Twig_Environment $env
520
- * @param mixed $number A float/int/string of the number to format
521
- * @param int $decimal the number of decimal points to display
522
- * @param string $decimalPoint the character(s) to use for the decimal point
523
- * @param string $thousandSep the character(s) to use for the thousands separator
524
- *
525
- * @return string The formatted number
526
- */
527
- function twig_number_format_filter(Twig_Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null)
528
- {
529
- $defaults = $env->getExtension('Twig_Extension_Core')->getNumberFormat();
530
- if (null === $decimal) {
531
- $decimal = $defaults[0];
532
- }
533
-
534
- if (null === $decimalPoint) {
535
- $decimalPoint = $defaults[1];
536
- }
537
-
538
- if (null === $thousandSep) {
539
- $thousandSep = $defaults[2];
540
- }
541
-
542
- return number_format((float) $number, $decimal, $decimalPoint, $thousandSep);
543
- }
544
-
545
- /**
546
- * URL encodes (RFC 3986) a string as a path segment or an array as a query string.
547
- *
548
- * @param string|array $url A URL or an array of query parameters
549
- *
550
- * @return string The URL encoded value
551
- */
552
- function twig_urlencode_filter($url)
553
- {
554
- if (is_array($url)) {
555
- if (defined('PHP_QUERY_RFC3986')) {
556
- return http_build_query($url, '', '&', PHP_QUERY_RFC3986);
557
- }
558
-
559
- return http_build_query($url, '', '&');
560
- }
561
-
562
- return rawurlencode($url);
563
- }
564
-
565
- /**
566
- * JSON encodes a variable.
567
- *
568
- * @param mixed $value the value to encode
569
- * @param int $options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT
570
- *
571
- * @return mixed The JSON encoded value
572
- */
573
- function twig_jsonencode_filter($value, $options = 0)
574
- {
575
- if ($value instanceof Twig_Markup) {
576
- $value = (string) $value;
577
- } elseif (is_array($value)) {
578
- array_walk_recursive($value, '_twig_markup2string');
579
- }
580
-
581
- return json_encode($value, $options);
582
- }
583
-
584
- function _twig_markup2string(&$value)
585
- {
586
- if ($value instanceof Twig_Markup) {
587
- $value = (string) $value;
588
- }
589
- }
590
-
591
- /**
592
- * Merges an array with another one.
593
- *
594
- * <pre>
595
- * {% set items = { 'apple': 'fruit', 'orange': 'fruit' } %}
596
- *
597
- * {% set items = items|merge({ 'peugeot': 'car' }) %}
598
- *
599
- * {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #}
600
- * </pre>
601
- *
602
- * @param array|Traversable $arr1 An array
603
- * @param array|Traversable $arr2 An array
604
- *
605
- * @return array The merged array
606
- */
607
- function twig_array_merge($arr1, $arr2)
608
- {
609
- if ($arr1 instanceof Traversable) {
610
- $arr1 = iterator_to_array($arr1);
611
- } elseif (!is_array($arr1)) {
612
- throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as first argument.', gettype($arr1)));
613
- }
614
-
615
- if ($arr2 instanceof Traversable) {
616
- $arr2 = iterator_to_array($arr2);
617
- } elseif (!is_array($arr2)) {
618
- throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as second argument.', gettype($arr2)));
619
- }
620
-
621
- return array_merge($arr1, $arr2);
622
- }
623
-
624
- /**
625
- * Slices a variable.
626
- *
627
- * @param Twig_Environment $env
628
- * @param mixed $item A variable
629
- * @param int $start Start of the slice
630
- * @param int $length Size of the slice
631
- * @param bool $preserveKeys Whether to preserve key or not (when the input is an array)
632
- *
633
- * @return mixed The sliced variable
634
- */
635
- function twig_slice(Twig_Environment $env, $item, $start, $length = null, $preserveKeys = false)
636
- {
637
- if ($item instanceof Traversable) {
638
- while ($item instanceof IteratorAggregate) {
639
- $item = $item->getIterator();
640
- }
641
-
642
- if ($start >= 0 && $length >= 0 && $item instanceof Iterator) {
643
- try {
644
- return iterator_to_array(new LimitIterator($item, $start, null === $length ? -1 : $length), $preserveKeys);
645
- } catch (OutOfBoundsException $exception) {
646
- return [];
647
- }
648
- }
649
-
650
- $item = iterator_to_array($item, $preserveKeys);
651
- }
652
-
653
- if (is_array($item)) {
654
- return array_slice($item, $start, $length, $preserveKeys);
655
- }
656
-
657
- $item = (string) $item;
658
-
659
- if (function_exists('mb_get_info') && null !== $charset = $env->getCharset()) {
660
- return (string) mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset);
661
- }
662
-
663
- return (string) (null === $length ? substr($item, $start) : substr($item, $start, $length));
664
- }
665
-
666
- /**
667
- * Returns the first element of the item.
668
- *
669
- * @param Twig_Environment $env
670
- * @param mixed $item A variable
671
- *
672
- * @return mixed The first element of the item
673
- */
674
- function twig_first(Twig_Environment $env, $item)
675
- {
676
- $elements = twig_slice($env, $item, 0, 1, false);
677
-
678
- return is_string($elements) ? $elements : current($elements);
679
- }
680
-
681
- /**
682
- * Returns the last element of the item.
683
- *
684
- * @param Twig_Environment $env
685
- * @param mixed $item A variable
686
- *
687
- * @return mixed The last element of the item
688
- */
689
- function twig_last(Twig_Environment $env, $item)
690
- {
691
- $elements = twig_slice($env, $item, -1, 1, false);
692
-
693
- return is_string($elements) ? $elements : current($elements);
694
- }
695
-
696
- /**
697
- * Joins the values to a string.
698
- *
699
- * The separators between elements are empty strings per default, you can define them with the optional parameters.
700
- *
701
- * <pre>
702
- * {{ [1, 2, 3]|join(', ', ' and ') }}
703
- * {# returns 1, 2 and 3 #}
704
- *
705
- * {{ [1, 2, 3]|join('|') }}
706
- * {# returns 1|2|3 #}
707
- *
708
- * {{ [1, 2, 3]|join }}
709
- * {# returns 123 #}
710
- * </pre>
711
- *
712
- * @param array $value An array
713
- * @param string $glue The separator
714
- * @param string|null $and The separator for the last pair
715
- *
716
- * @return string The concatenated string
717
- */
718
- function twig_join_filter($value, $glue = '', $and = null)
719
- {
720
- if ($value instanceof Traversable) {
721
- $value = iterator_to_array($value, false);
722
- } else {
723
- $value = (array) $value;
724
- }
725
-
726
- if (0 === count($value)) {
727
- return '';
728
- }
729
-
730
- if (null === $and || $and === $glue) {
731
- return implode($glue, $value);
732
- }
733
-
734
- $v = array_values($value);
735
- if (1 === count($v)) {
736
- return $v[0];
737
- }
738
-
739
- return implode($glue, array_slice($value, 0, -1)).$and.$v[count($v) - 1];
740
- }
741
-
742
- /**
743
- * Splits the string into an array.
744
- *
745
- * <pre>
746
- * {{ "one,two,three"|split(',') }}
747
- * {# returns [one, two, three] #}
748
- *
749
- * {{ "one,two,three,four,five"|split(',', 3) }}
750
- * {# returns [one, two, "three,four,five"] #}
751
- *
752
- * {{ "123"|split('') }}
753
- * {# returns [1, 2, 3] #}
754
- *
755
- * {{ "aabbcc"|split('', 2) }}
756
- * {# returns [aa, bb, cc] #}
757
- * </pre>
758
- *
759
- * @param Twig_Environment $env
760
- * @param string $value A string
761
- * @param string $delimiter The delimiter
762
- * @param int $limit The limit
763
- *
764
- * @return array The split string as an array
765
- */
766
- function twig_split_filter(Twig_Environment $env, $value, $delimiter, $limit = null)
767
- {
768
- if (!empty($delimiter)) {
769
- return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit);
770
- }
771
-
772
- if (!function_exists('mb_get_info') || null === $charset = $env->getCharset()) {
773
- return str_split($value, null === $limit ? 1 : $limit);
774
- }
775
-
776
- if ($limit <= 1) {
777
- return preg_split('/(?<!^)(?!$)/u', $value);
778
- }
779
-
780
- $length = mb_strlen($value, $charset);
781
- if ($length < $limit) {
782
- return [$value];
783
- }
784
-
785
- $r = [];
786
- for ($i = 0; $i < $length; $i += $limit) {
787
- $r[] = mb_substr($value, $i, $limit, $charset);
788
- }
789
-
790
- return $r;
791
- }
792
-
793
- // The '_default' filter is used internally to avoid using the ternary operator
794
- // which costs a lot for big contexts (before PHP 5.4). So, on average,
795
- // a function call is cheaper.
796
- /**
797
- * @internal
798
- */
799
- function _twig_default_filter($value, $default = '')
800
- {
801
- if (twig_test_empty($value)) {
802
- return $default;
803
- }
804
-
805
- return $value;
806
- }
807
-
808
- /**
809
- * Returns the keys for the given array.
810
- *
811
- * It is useful when you want to iterate over the keys of an array:
812
- *
813
- * <pre>
814
- * {% for key in array|keys %}
815
- * {# ... #}
816
- * {% endfor %}
817
- * </pre>
818
- *
819
- * @param array $array An array
820
- *
821
- * @return array The keys
822
- */
823
- function twig_get_array_keys_filter($array)
824
- {
825
- if ($array instanceof Traversable) {
826
- while ($array instanceof IteratorAggregate) {
827
- $array = $array->getIterator();
828
- }
829
-
830
- if ($array instanceof Iterator) {
831
- $keys = [];
832
- $array->rewind();
833
- while ($array->valid()) {
834
- $keys[] = $array->key();
835
- $array->next();
836
- }
837
-
838
- return $keys;
839
- }
840
-
841
- $keys = [];
842
- foreach ($array as $key => $item) {
843
- $keys[] = $key;
844
- }
845
-
846
- return $keys;
847
- }
848
-
849
- if (!is_array($array)) {
850
- return [];
851
- }
852
-
853
- return array_keys($array);
854
- }
855
 
856
- /**
857
- * Reverses a variable.
858
- *
859
- * @param Twig_Environment $env
860
- * @param array|Traversable|string $item An array, a Traversable instance, or a string
861
- * @param bool $preserveKeys Whether to preserve key or not
862
- *
863
- * @return mixed The reversed input
864
- */
865
- function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false)
866
- {
867
- if ($item instanceof Traversable) {
868
- return array_reverse(iterator_to_array($item), $preserveKeys);
869
- }
870
-
871
- if (is_array($item)) {
872
- return array_reverse($item, $preserveKeys);
873
- }
874
-
875
- if (null !== $charset = $env->getCharset()) {
876
- $string = (string) $item;
877
-
878
- if ('UTF-8' !== $charset) {
879
- $item = twig_convert_encoding($string, 'UTF-8', $charset);
880
- }
881
-
882
- preg_match_all('/./us', $item, $matches);
883
-
884
- $string = implode('', array_reverse($matches[0]));
885
-
886
- if ('UTF-8' !== $charset) {
887
- $string = twig_convert_encoding($string, $charset, 'UTF-8');
888
- }
889
-
890
- return $string;
891
- }
892
-
893
- return strrev((string) $item);
894
- }
895
-
896
- /**
897
- * Sorts an array.
898
- *
899
- * @param array|Traversable $array
900
- *
901
- * @return array
902
- */
903
- function twig_sort_filter($array)
904
- {
905
- if ($array instanceof Traversable) {
906
- $array = iterator_to_array($array);
907
- } elseif (!is_array($array)) {
908
- throw new Twig_Error_Runtime(sprintf('The sort filter only works with arrays or "Traversable", got "%s".', gettype($array)));
909
- }
910
-
911
- asort($array);
912
-
913
- return $array;
914
- }
915
-
916
- /**
917
- * @internal
918
- */
919
- function twig_in_filter($value, $compare)
920
- {
921
- if (is_array($compare)) {
922
- return in_array($value, $compare, is_object($value) || is_resource($value));
923
- } elseif (is_string($compare) && (is_string($value) || is_int($value) || is_float($value))) {
924
- return '' === $value || false !== strpos($compare, (string) $value);
925
- } elseif ($compare instanceof Traversable) {
926
- if (is_object($value) || is_resource($value)) {
927
- foreach ($compare as $item) {
928
- if ($item === $value) {
929
- return true;
930
- }
931
- }
932
- } else {
933
- foreach ($compare as $item) {
934
- if ($item == $value) {
935
- return true;
936
- }
937
- }
938
- }
939
-
940
- return false;
941
- }
942
-
943
- return false;
944
- }
945
-
946
- /**
947
- * Returns a trimmed string.
948
- *
949
- * @return string
950
- *
951
- * @throws Twig_Error_Runtime When an invalid trimming side is used (not a string or not 'left', 'right', or 'both')
952
- */
953
- function twig_trim_filter($string, $characterMask = null, $side = 'both')
954
- {
955
- if (null === $characterMask) {
956
- $characterMask = " \t\n\r\0\x0B";
957
- }
958
-
959
- switch ($side) {
960
- case 'both':
961
- return trim($string, $characterMask);
962
- case 'left':
963
- return ltrim($string, $characterMask);
964
- case 'right':
965
- return rtrim($string, $characterMask);
966
- default:
967
- throw new Twig_Error_Runtime('Trimming side must be "left", "right" or "both".');
968
- }
969
- }
970
-
971
- /**
972
- * Escapes a string.
973
- *
974
- * @param Twig_Environment $env
975
- * @param mixed $string The value to be escaped
976
- * @param string $strategy The escaping strategy
977
- * @param string $charset The charset
978
- * @param bool $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false)
979
- *
980
- * @return string
981
- */
982
- function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
983
- {
984
- if ($autoescape && $string instanceof Twig_Markup) {
985
- return $string;
986
- }
987
-
988
- if (!is_string($string)) {
989
- if (is_object($string) && method_exists($string, '__toString')) {
990
- $string = (string) $string;
991
- } elseif (in_array($strategy, ['html', 'js', 'css', 'html_attr', 'url'])) {
992
- return $string;
993
- }
994
- }
995
-
996
- if ('' === $string) {
997
- return '';
998
- }
999
-
1000
- if (null === $charset) {
1001
- $charset = $env->getCharset();
1002
- }
1003
-
1004
- switch ($strategy) {
1005
- case 'html':
1006
- // see https://secure.php.net/htmlspecialchars
1007
-
1008
- // Using a static variable to avoid initializing the array
1009
- // each time the function is called. Moving the declaration on the
1010
- // top of the function slow downs other escaping strategies.
1011
- static $htmlspecialcharsCharsets = [
1012
- 'ISO-8859-1' => true, 'ISO8859-1' => true,
1013
- 'ISO-8859-15' => true, 'ISO8859-15' => true,
1014
- 'utf-8' => true, 'UTF-8' => true,
1015
- 'CP866' => true, 'IBM866' => true, '866' => true,
1016
- 'CP1251' => true, 'WINDOWS-1251' => true, 'WIN-1251' => true,
1017
- '1251' => true,
1018
- 'CP1252' => true, 'WINDOWS-1252' => true, '1252' => true,
1019
- 'KOI8-R' => true, 'KOI8-RU' => true, 'KOI8R' => true,
1020
- 'BIG5' => true, '950' => true,
1021
- 'GB2312' => true, '936' => true,
1022
- 'BIG5-HKSCS' => true,
1023
- 'SHIFT_JIS' => true, 'SJIS' => true, '932' => true,
1024
- 'EUC-JP' => true, 'EUCJP' => true,
1025
- 'ISO8859-5' => true, 'ISO-8859-5' => true, 'MACROMAN' => true,
1026
- ];
1027
-
1028
- if (isset($htmlspecialcharsCharsets[$charset])) {
1029
- return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
1030
- }
1031
-
1032
- if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) {
1033
- // cache the lowercase variant for future iterations
1034
- $htmlspecialcharsCharsets[$charset] = true;
1035
-
1036
- return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
1037
- }
1038
-
1039
- $string = twig_convert_encoding($string, 'UTF-8', $charset);
1040
- $string = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
1041
-
1042
- return twig_convert_encoding($string, $charset, 'UTF-8');
1043
-
1044
- case 'js':
1045
- // escape all non-alphanumeric characters
1046
- // into their \x or \uHHHH representations
1047
- if ('UTF-8' !== $charset) {
1048
- $string = twig_convert_encoding($string, 'UTF-8', $charset);
1049
- }
1050
-
1051
- if (!preg_match('//u', $string)) {
1052
- throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
1053
- }
1054
-
1055
- $string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', '_twig_escape_js_callback', $string);
1056
-
1057
- if ('UTF-8' !== $charset) {
1058
- $string = twig_convert_encoding($string, $charset, 'UTF-8');
1059
- }
1060
-
1061
- return $string;
1062
-
1063
- case 'css':
1064
- if ('UTF-8' !== $charset) {
1065
- $string = twig_convert_encoding($string, 'UTF-8', $charset);
1066
- }
1067
-
1068
- if (!preg_match('//u', $string)) {
1069
- throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
1070
- }
1071
-
1072
- $string = preg_replace_callback('#[^a-zA-Z0-9]#Su', '_twig_escape_css_callback', $string);
1073
-
1074
- if ('UTF-8' !== $charset) {
1075
- $string = twig_convert_encoding($string, $charset, 'UTF-8');
1076
- }
1077
-
1078
- return $string;
1079
-
1080
- case 'html_attr':
1081
- if ('UTF-8' !== $charset) {
1082
- $string = twig_convert_encoding($string, 'UTF-8', $charset);
1083
- }
1084
-
1085
- if (!preg_match('//u', $string)) {
1086
- throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
1087
- }
1088
-
1089
- $string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', '_twig_escape_html_attr_callback', $string);
1090
-
1091
- if ('UTF-8' !== $charset) {
1092
- $string = twig_convert_encoding($string, $charset, 'UTF-8');
1093
- }
1094
-
1095
- return $string;
1096
-
1097
- case 'url':
1098
- return rawurlencode($string);
1099
-
1100
- default:
1101
- static $escapers;
1102
-
1103
- if (null === $escapers) {
1104
- $escapers = $env->getExtension('Twig_Extension_Core')->getEscapers();
1105
- }
1106
-
1107
- if (isset($escapers[$strategy])) {
1108
- return call_user_func($escapers[$strategy], $env, $string, $charset);
1109
- }
1110
-
1111
- $validStrategies = implode(', ', array_merge(['html', 'js', 'url', 'css', 'html_attr'], array_keys($escapers)));
1112
-
1113
- throw new Twig_Error_Runtime(sprintf('Invalid escaping strategy "%s" (valid ones: %s).', $strategy, $validStrategies));
1114
- }
1115
- }
1116
-
1117
- /**
1118
- * @internal
1119
- */
1120
- function twig_escape_filter_is_safe(Twig_Node $filterArgs)
1121
- {
1122
- foreach ($filterArgs as $arg) {
1123
- if ($arg instanceof Twig_Node_Expression_Constant) {
1124
- return [$arg->getAttribute('value')];
1125
- }
1126
-
1127
- return [];
1128
- }
1129
-
1130
- return ['html'];
1131
- }
1132
-
1133
- if (function_exists('mb_convert_encoding')) {
1134
- function twig_convert_encoding($string, $to, $from)
1135
- {
1136
- return mb_convert_encoding($string, $to, $from);
1137
- }
1138
- } elseif (function_exists('iconv')) {
1139
- function twig_convert_encoding($string, $to, $from)
1140
- {
1141
- return iconv($from, $to, $string);
1142
- }
1143
- } else {
1144
- function twig_convert_encoding($string, $to, $from)
1145
- {
1146
- throw new Twig_Error_Runtime('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).');
1147
- }
1148
- }
1149
-
1150
- if (function_exists('mb_ord')) {
1151
- function twig_ord($string)
1152
- {
1153
- return mb_ord($string, 'UTF-8');
1154
- }
1155
- } else {
1156
- function twig_ord($string)
1157
- {
1158
- $code = ($string = unpack('C*', substr($string, 0, 4))) ? $string[1] : 0;
1159
- if (0xF0 <= $code) {
1160
- return (($code - 0xF0) << 18) + (($string[2] - 0x80) << 12) + (($string[3] - 0x80) << 6) + $string[4] - 0x80;
1161
- }
1162
- if (0xE0 <= $code) {
1163
- return (($code - 0xE0) << 12) + (($string[2] - 0x80) << 6) + $string[3] - 0x80;
1164
- }
1165
- if (0xC0 <= $code) {
1166
- return (($code - 0xC0) << 6) + $string[2] - 0x80;
1167
- }
1168
-
1169
- return $code;
1170
- }
1171
- }
1172
-
1173
- function _twig_escape_js_callback($matches)
1174
- {
1175
- $char = $matches[0];
1176
-
1177
- /*
1178
- * A few characters have short escape sequences in JSON and JavaScript.
1179
- * Escape sequences supported only by JavaScript, not JSON, are ommitted.
1180
- * \" is also supported but omitted, because the resulting string is not HTML safe.
1181
- */
1182
- static $shortMap = [
1183
- '\\' => '\\\\',
1184
- '/' => '\\/',
1185
- "\x08" => '\b',
1186
- "\x0C" => '\f',
1187
- "\x0A" => '\n',
1188
- "\x0D" => '\r',
1189
- "\x09" => '\t',
1190
- ];
1191
-
1192
- if (isset($shortMap[$char])) {
1193
- return $shortMap[$char];
1194
- }
1195
-
1196
- // \uHHHH
1197
- $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');
1198
- $char = strtoupper(bin2hex($char));
1199
-
1200
- if (4 >= strlen($char)) {
1201
- return sprintf('\u%04s', $char);
1202
- }
1203
-
1204
- return sprintf('\u%04s\u%04s', substr($char, 0, -4), substr($char, -4));
1205
- }
1206
 
1207
- function _twig_escape_css_callback($matches)
1208
- {
1209
- $char = $matches[0];
1210
-
1211
- return sprintf('\\%X ', 1 === strlen($char) ? ord($char) : twig_ord($char));
1212
- }
1213
-
1214
- /**
1215
- * This function is adapted from code coming from Zend Framework.
1216
- *
1217
- * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (https://www.zend.com)
1218
- * @license https://framework.zend.com/license/new-bsd New BSD License
1219
- */
1220
- function _twig_escape_html_attr_callback($matches)
1221
- {
1222
- $chr = $matches[0];
1223
- $ord = ord($chr);
1224
-
1225
- /*
1226
- * The following replaces characters undefined in HTML with the
1227
- * hex entity for the Unicode replacement character.
1228
- */
1229
- if (($ord <= 0x1f && "\t" != $chr && "\n" != $chr && "\r" != $chr) || ($ord >= 0x7f && $ord <= 0x9f)) {
1230
- return '&#xFFFD;';
1231
- }
1232
-
1233
- /*
1234
- * Check if the current character to escape has a name entity we should
1235
- * replace it with while grabbing the hex value of the character.
1236
- */
1237
- if (1 == strlen($chr)) {
1238
- /*
1239
- * While HTML supports far more named entities, the lowest common denominator
1240
- * has become HTML5's XML Serialisation which is restricted to the those named
1241
- * entities that XML supports. Using HTML entities would result in this error:
1242
- * XML Parsing Error: undefined entity
1243
- */
1244
- static $entityMap = [
1245
- 34 => '&quot;', /* quotation mark */
1246
- 38 => '&amp;', /* ampersand */
1247
- 60 => '&lt;', /* less-than sign */
1248
- 62 => '&gt;', /* greater-than sign */
1249
- ];
1250
-
1251
- if (isset($entityMap[$ord])) {
1252
- return $entityMap[$ord];
1253
- }
1254
-
1255
- return sprintf('&#x%02X;', $ord);
1256
- }
1257
-
1258
- /*
1259
- * Per OWASP recommendations, we'll use hex entities for any other
1260
- * characters where a named entity does not exist.
1261
- */
1262
- return sprintf('&#x%04X;', twig_ord($chr));
1263
- }
1264
-
1265
- // add multibyte extensions if possible
1266
- if (function_exists('mb_get_info')) {
1267
- /**
1268
- * Returns the length of a variable.
1269
- *
1270
- * @param Twig_Environment $env
1271
- * @param mixed $thing A variable
1272
- *
1273
- * @return int The length of the value
1274
- */
1275
- function twig_length_filter(Twig_Environment $env, $thing)
1276
- {
1277
- if (null === $thing) {
1278
- return 0;
1279
- }
1280
-
1281
- if (is_scalar($thing)) {
1282
- return mb_strlen($thing, $env->getCharset());
1283
- }
1284
-
1285
- if ($thing instanceof \SimpleXMLElement) {
1286
- return count($thing);
1287
- }
1288
-
1289
- if (is_object($thing) && method_exists($thing, '__toString') && !$thing instanceof \Countable) {
1290
- return mb_strlen((string) $thing, $env->getCharset());
1291
- }
1292
-
1293
- if ($thing instanceof \Countable || is_array($thing)) {
1294
- return count($thing);
1295
- }
1296
-
1297
- if ($thing instanceof \IteratorAggregate) {
1298
- return iterator_count($thing);
1299
- }
1300
-
1301
- return 1;
1302
- }
1303
-
1304
- /**
1305
- * Converts a string to uppercase.
1306
- *
1307
- * @param Twig_Environment $env
1308
- * @param string $string A string
1309
- *
1310
- * @return string The uppercased string
1311
- */
1312
- function twig_upper_filter(Twig_Environment $env, $string)
1313
- {
1314
- if (null !== $charset = $env->getCharset()) {
1315
- return mb_strtoupper($string, $charset);
1316
- }
1317
-
1318
- return strtoupper($string);
1319
- }
1320
-
1321
- /**
1322
- * Converts a string to lowercase.
1323
- *
1324
- * @param Twig_Environment $env
1325
- * @param string $string A string
1326
- *
1327
- * @return string The lowercased string
1328
- */
1329
- function twig_lower_filter(Twig_Environment $env, $string)
1330
- {
1331
- if (null !== $charset = $env->getCharset()) {
1332
- return mb_strtolower($string, $charset);
1333
- }
1334
-
1335
- return strtolower($string);
1336
- }
1337
-
1338
- /**
1339
- * Returns a titlecased string.
1340
- *
1341
- * @param Twig_Environment $env
1342
- * @param string $string A string
1343
- *
1344
- * @return string The titlecased string
1345
- */
1346
- function twig_title_string_filter(Twig_Environment $env, $string)
1347
- {
1348
- if (null !== $charset = $env->getCharset()) {
1349
- return mb_convert_case($string, MB_CASE_TITLE, $charset);
1350
- }
1351
-
1352
- return ucwords(strtolower($string));
1353
- }
1354
-
1355
- /**
1356
- * Returns a capitalized string.
1357
- *
1358
- * @param Twig_Environment $env
1359
- * @param string $string A string
1360
- *
1361
- * @return string The capitalized string
1362
- */
1363
- function twig_capitalize_string_filter(Twig_Environment $env, $string)
1364
- {
1365
- if (null !== $charset = $env->getCharset()) {
1366
- return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset).mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset);
1367
- }
1368
-
1369
- return ucfirst(strtolower($string));
1370
- }
1371
- }
1372
- // and byte fallback
1373
- else {
1374
- /**
1375
- * Returns the length of a variable.
1376
- *
1377
- * @param Twig_Environment $env
1378
- * @param mixed $thing A variable
1379
- *
1380
- * @return int The length of the value
1381
- */
1382
- function twig_length_filter(Twig_Environment $env, $thing)
1383
- {
1384
- if (null === $thing) {
1385
- return 0;
1386
- }
1387
-
1388
- if (is_scalar($thing)) {
1389
- return strlen($thing);
1390
- }
1391
-
1392
- if ($thing instanceof \SimpleXMLElement) {
1393
- return count($thing);
1394
- }
1395
-
1396
- if (is_object($thing) && method_exists($thing, '__toString') && !$thing instanceof \Countable) {
1397
- return strlen((string) $thing);
1398
- }
1399
-
1400
- if ($thing instanceof \Countable || is_array($thing)) {
1401
- return count($thing);
1402
- }
1403
-
1404
- if ($thing instanceof \IteratorAggregate) {
1405
- return iterator_count($thing);
1406
- }
1407
-
1408
- return 1;
1409
- }
1410
-
1411
- /**
1412
- * Returns a titlecased string.
1413
- *
1414
- * @param Twig_Environment $env
1415
- * @param string $string A string
1416
- *
1417
- * @return string The titlecased string
1418
- */
1419
- function twig_title_string_filter(Twig_Environment $env, $string)
1420
- {
1421
- return ucwords(strtolower($string));
1422
- }
1423
-
1424
- /**
1425
- * Returns a capitalized string.
1426
- *
1427
- * @param Twig_Environment $env
1428
- * @param string $string A string
1429
- *
1430
- * @return string The capitalized string
1431
- */
1432
- function twig_capitalize_string_filter(Twig_Environment $env, $string)
1433
  {
1434
- return ucfirst(strtolower($string));
1435
- }
1436
- }
1437
-
1438
- /**
1439
- * @internal
1440
- */
1441
- function twig_ensure_traversable($seq)
1442
- {
1443
- if ($seq instanceof Traversable || is_array($seq)) {
1444
- return $seq;
1445
- }
1446
-
1447
- return [];
1448
- }
1449
-
1450
- /**
1451
- * Checks if a variable is empty.
1452
- *
1453
- * <pre>
1454
- * {# evaluates to true if the foo variable is null, false, or the empty string #}
1455
- * {% if foo is empty %}
1456
- * {# ... #}
1457
- * {% endif %}
1458
- * </pre>
1459
- *
1460
- * @param mixed $value A variable
1461
- *
1462
- * @return bool true if the value is empty, false otherwise
1463
- */
1464
- function twig_test_empty($value)
1465
- {
1466
- if ($value instanceof Countable) {
1467
- return 0 == count($value);
1468
  }
1469
-
1470
- if (is_object($value) && method_exists($value, '__toString')) {
1471
- return '' === (string) $value;
1472
- }
1473
-
1474
- return '' === $value || false === $value || null === $value || [] === $value;
1475
  }
1476
-
1477
- /**
1478
- * Checks if a variable is traversable.
1479
- *
1480
- * <pre>
1481
- * {# evaluates to true if the foo variable is an array or a traversable object #}
1482
- * {% if foo is iterable %}
1483
- * {# ... #}
1484
- * {% endif %}
1485
- * </pre>
1486
- *
1487
- * @param mixed $value A variable
1488
- *
1489
- * @return bool true if the value is traversable
1490
- */
1491
- function twig_test_iterable($value)
1492
- {
1493
- return $value instanceof Traversable || is_array($value);
1494
- }
1495
-
1496
- /**
1497
- * Renders a template.
1498
- *
1499
- * @param Twig_Environment $env
1500
- * @param array $context
1501
- * @param string|array $template The template to render or an array of templates to try consecutively
1502
- * @param array $variables The variables to pass to the template
1503
- * @param bool $withContext
1504
- * @param bool $ignoreMissing Whether to ignore missing templates or not
1505
- * @param bool $sandboxed Whether to sandbox the template or not
1506
- *
1507
- * @return string The rendered template
1508
- */
1509
- function twig_include(Twig_Environment $env, $context, $template, $variables = [], $withContext = true, $ignoreMissing = false, $sandboxed = false)
1510
- {
1511
- $alreadySandboxed = false;
1512
- $sandbox = null;
1513
- if ($withContext) {
1514
- $variables = array_merge($context, $variables);
1515
- }
1516
-
1517
- if ($isSandboxed = $sandboxed && $env->hasExtension('Twig_Extension_Sandbox')) {
1518
- $sandbox = $env->getExtension('Twig_Extension_Sandbox');
1519
- if (!$alreadySandboxed = $sandbox->isSandboxed()) {
1520
- $sandbox->enableSandbox();
1521
- }
1522
- }
1523
-
1524
- $result = '';
1525
- try {
1526
- $result = $env->resolveTemplate($template)->render($variables);
1527
- } catch (Twig_Error_Loader $e) {
1528
- if (!$ignoreMissing) {
1529
- if ($isSandboxed && !$alreadySandboxed) {
1530
- $sandbox->disableSandbox();
1531
- }
1532
-
1533
- throw $e;
1534
- }
1535
- } catch (Throwable $e) {
1536
- if ($isSandboxed && !$alreadySandboxed) {
1537
- $sandbox->disableSandbox();
1538
- }
1539
-
1540
- throw $e;
1541
- } catch (Exception $e) {
1542
- if ($isSandboxed && !$alreadySandboxed) {
1543
- $sandbox->disableSandbox();
1544
- }
1545
-
1546
- throw $e;
1547
- }
1548
-
1549
- if ($isSandboxed && !$alreadySandboxed) {
1550
- $sandbox->disableSandbox();
1551
- }
1552
-
1553
- return $result;
1554
- }
1555
-
1556
- /**
1557
- * Returns a template content without rendering it.
1558
- *
1559
- * @param Twig_Environment $env
1560
- * @param string $name The template name
1561
- * @param bool $ignoreMissing Whether to ignore missing templates or not
1562
- *
1563
- * @return string The template source
1564
- */
1565
- function twig_source(Twig_Environment $env, $name, $ignoreMissing = false)
1566
- {
1567
- $loader = $env->getLoader();
1568
- try {
1569
- if (!$loader instanceof Twig_SourceContextLoaderInterface) {
1570
- return $loader->getSource($name);
1571
- } else {
1572
- return $loader->getSourceContext($name)->getCode();
1573
- }
1574
- } catch (Twig_Error_Loader $e) {
1575
- if (!$ignoreMissing) {
1576
- throw $e;
1577
- }
1578
- }
1579
- }
1580
-
1581
- /**
1582
- * Provides the ability to get constants from instances as well as class/global constants.
1583
- *
1584
- * @param string $constant The name of the constant
1585
- * @param object|null $object The object to get the constant from
1586
- *
1587
- * @return string
1588
- */
1589
- function twig_constant($constant, $object = null)
1590
- {
1591
- if (null !== $object) {
1592
- $constant = get_class($object).'::'.$constant;
1593
- }
1594
-
1595
- return constant($constant);
1596
- }
1597
-
1598
- /**
1599
- * Checks if a constant exists.
1600
- *
1601
- * @param string $constant The name of the constant
1602
- * @param object|null $object The object to get the constant from
1603
- *
1604
- * @return bool
1605
- */
1606
- function twig_constant_is_defined($constant, $object = null)
1607
- {
1608
- if (null !== $object) {
1609
- $constant = get_class($object).'::'.$constant;
1610
- }
1611
-
1612
- return defined($constant);
1613
- }
1614
-
1615
- /**
1616
- * Batches item.
1617
- *
1618
- * @param array $items An array of items
1619
- * @param int $size The size of the batch
1620
- * @param mixed $fill A value used to fill missing items
1621
- *
1622
- * @return array
1623
- */
1624
- function twig_array_batch($items, $size, $fill = null)
1625
- {
1626
- if ($items instanceof Traversable) {
1627
- $items = iterator_to_array($items, false);
1628
- }
1629
-
1630
- $size = ceil($size);
1631
-
1632
- $result = array_chunk($items, $size, true);
1633
-
1634
- if (null !== $fill && !empty($result)) {
1635
- $last = count($result) - 1;
1636
- if ($fillCount = $size - count($result[$last])) {
1637
- $result[$last] = array_merge(
1638
- $result[$last],
1639
- array_fill(0, $fillCount, $fill)
1640
- );
1641
- }
1642
- }
1643
-
1644
- return $result;
1645
- }
1646
-
1647
- class_alias('Twig_Extension_Core', 'Twig\Extension\CoreExtension', false);
1
  <?php
2
 
3
+ use Twig\Extension\CoreExtension;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Extension\CoreExtension');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Extension_Core extends CoreExtension
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
 
 
 
 
 
 
11
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/vendor/twig/twig/lib/Twig/Extension/Debug.php CHANGED
@@ -1,67 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * @final
14
- */
15
- class Twig_Extension_Debug extends Twig_Extension
16
- {
17
- public function getFunctions()
18
- {
19
- // dump is safe if var_dump is overridden by xdebug
20
- $isDumpOutputHtmlSafe = extension_loaded('xdebug')
21
- // false means that it was not set (and the default is on) or it explicitly enabled
22
- && (false === ini_get('xdebug.overload_var_dump') || ini_get('xdebug.overload_var_dump'))
23
- // false means that it was not set (and the default is on) or it explicitly enabled
24
- // xdebug.overload_var_dump produces HTML only when html_errors is also enabled
25
- && (false === ini_get('html_errors') || ini_get('html_errors'))
26
- || 'cli' === PHP_SAPI
27
- ;
28
-
29
- return [
30
- new Twig_SimpleFunction('dump', 'twig_var_dump', ['is_safe' => $isDumpOutputHtmlSafe ? ['html'] : [], 'needs_context' => true, 'needs_environment' => true]),
31
- ];
32
- }
33
 
34
- public function getName()
 
35
  {
36
- return 'debug';
37
- }
38
- }
39
-
40
- function twig_var_dump(Twig_Environment $env, $context)
41
- {
42
- if (!$env->isDebug()) {
43
- return;
44
  }
45
-
46
- ob_start();
47
-
48
- $count = func_num_args();
49
- if (2 === $count) {
50
- $vars = [];
51
- foreach ($context as $key => $value) {
52
- if (!$value instanceof Twig_Template) {
53
- $vars[$key] = $value;
54
- }
55
- }
56
-
57
- var_dump($vars);
58
- } else {
59
- for ($i = 2; $i < $count; ++$i) {
60
- var_dump(func_get_arg($i));
61
- }
62
- }
63
-
64
- return ob_get_clean();
65
  }
66
-
67
- class_alias('Twig_Extension_Debug', 'Twig\Extension\DebugExtension', false);
1
  <?php
2
 
3
+ use Twig\Extension\DebugExtension;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Extension\DebugExtension');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Extension_Debug extends DebugExtension
9
  {
 
 
 
 
 
 
 
 
10
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Extension/Escaper.php CHANGED
@@ -1,112 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * @final
14
- */
15
- class Twig_Extension_Escaper extends Twig_Extension
16
- {
17
- protected $defaultStrategy;
18
 
19
- /**
20
- * @param string|false|callable $defaultStrategy An escaping strategy
21
- *
22
- * @see setDefaultStrategy()
23
- */
24
- public function __construct($defaultStrategy = 'html')
25
  {
26
- $this->setDefaultStrategy($defaultStrategy);
27
- }
28
-
29
- public function getTokenParsers()
30
- {
31
- return [new Twig_TokenParser_AutoEscape()];
32
- }
33
-
34
- public function getNodeVisitors()
35
- {
36
- return [new Twig_NodeVisitor_Escaper()];
37
- }
38
-
39
- public function getFilters()
40
- {
41
- return [
42
- new Twig_SimpleFilter('raw', 'twig_raw_filter', ['is_safe' => ['all']]),
43
- ];
44
- }
45
-
46
- /**
47
- * Sets the default strategy to use when not defined by the user.
48
- *
49
- * The strategy can be a valid PHP callback that takes the template
50
- * name as an argument and returns the strategy to use.
51
- *
52
- * @param string|false|callable $defaultStrategy An escaping strategy
53
- */
54
- public function setDefaultStrategy($defaultStrategy)
55
- {
56
- // for BC
57
- if (true === $defaultStrategy) {
58
- @trigger_error('Using "true" as the default strategy is deprecated since version 1.21. Use "html" instead.', E_USER_DEPRECATED);
59
-
60
- $defaultStrategy = 'html';
61
- }
62
-
63
- if ('filename' === $defaultStrategy) {
64
- @trigger_error('Using "filename" as the default strategy is deprecated since version 1.27. Use "name" instead.', E_USER_DEPRECATED);
65
-
66
- $defaultStrategy = 'name';
67
- }
68
-
69
- if ('name' === $defaultStrategy) {
70
- $defaultStrategy = ['Twig_FileExtensionEscapingStrategy', 'guess'];
71
- }
72
-
73
- $this->defaultStrategy = $defaultStrategy;
74
- }
75
-
76
- /**
77
- * Gets the default strategy to use when not defined by the user.
78
- *
79
- * @param string $name The template name
80
- *
81
- * @return string|false The default strategy to use for the template
82
- */
83
- public function getDefaultStrategy($name)
84
- {
85
- // disable string callables to avoid calling a function named html or js,
86
- // or any other upcoming escaping strategy
87
- if (!is_string($this->defaultStrategy) && false !== $this->defaultStrategy) {
88
- return call_user_func($this->defaultStrategy, $name);
89
- }
90
-
91
- return $this->defaultStrategy;
92
- }
93
-
94
- public function getName()
95
- {
96
- return 'escaper';
97
  }
98
  }
99
-
100
- /**
101
- * Marks a variable as being safe.
102
- *
103
- * @param string $string A PHP variable
104
- *
105
- * @return string
106
- */
107
- function twig_raw_filter($string)
108
- {
109
- return $string;
110
- }
111
-
112
- class_alias('Twig_Extension_Escaper', 'Twig\Extension\EscaperExtension', false);
1
  <?php
2
 
3
+ use Twig\Extension\EscaperExtension;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Extension\EscaperExtension');
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Extension_Escaper extends EscaperExtension
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/vendor/twig/twig/lib/Twig/Extension/GlobalsInterface.php CHANGED
@@ -1,24 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Enables usage of the deprecated Twig_Extension::getGlobals() method.
14
- *
15
- * Explicitly implement this interface if you really need to implement the
16
- * deprecated getGlobals() method in your extensions.
17
- *
18
- * @author Fabien Potencier <fabien@symfony.com>
19
- */
20
- interface Twig_Extension_GlobalsInterface
21
- {
22
- }
23
 
24
- class_alias('Twig_Extension_GlobalsInterface', 'Twig\Extension\GlobalsInterface', false);
 
 
 
 
1
  <?php
2
 
3
+ use Twig\Extension\GlobalsInterface;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Extension\GlobalsInterface');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Extension_GlobalsInterface extends GlobalsInterface
9
+ {
10
+ }
11
+ }
src/lib/vendor/twig/twig/lib/Twig/Extension/InitRuntimeInterface.php CHANGED
@@ -1,24 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Enables usage of the deprecated Twig_Extension::initRuntime() method.
14
- *
15
- * Explicitly implement this interface if you really need to implement the
16
- * deprecated initRuntime() method in your extensions.
17
- *
18
- * @author Fabien Potencier <fabien@symfony.com>
19
- */
20
- interface Twig_Extension_InitRuntimeInterface
21
- {
22
- }
23
 
24
- class_alias('Twig_Extension_InitRuntimeInterface', 'Twig\Extension\InitRuntimeInterface', false);
 
 
 
 
1
  <?php
2
 
3
+ use Twig\Extension\InitRuntimeInterface;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Extension\InitRuntimeInterface');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Extension_InitRuntimeInterface extends InitRuntimeInterface
9
+ {
10
+ }
11
+ }
src/lib/vendor/twig/twig/lib/Twig/Extension/Optimizer.php CHANGED
@@ -1,35 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * @final
14
- */
15
- class Twig_Extension_Optimizer extends Twig_Extension
16
- {
17
- protected $optimizers;
18
 
19
- public function __construct($optimizers = -1)
 
20
  {
21
- $this->optimizers = $optimizers;
22
- }
23
-
24
- public function getNodeVisitors()
25
- {
26
- return [new Twig_NodeVisitor_Optimizer($this->optimizers)];
27
- }
28
-
29
- public function getName()
30
- {
31
- return 'optimizer';
32
  }
33
  }
34
-
35
- class_alias('Twig_Extension_Optimizer', 'Twig\Extension\OptimizerExtension', false);
1
  <?php
2
 
3
+ use Twig\Extension\OptimizerExtension;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Extension\OptimizerExtension');
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Extension_Optimizer extends OptimizerExtension
9
  {
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Extension/Profiler.php CHANGED
@@ -1,49 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- class Twig_Extension_Profiler extends Twig_Extension
13
- {
14
- private $actives = [];
15
 
16
- public function __construct(Twig_Profiler_Profile $profile)
 
17
  {
18
- $this->actives[] = $profile;
19
- }
20
-
21
- public function enter(Twig_Profiler_Profile $profile)
22
- {
23
- $this->actives[0]->addProfile($profile);
24
- array_unshift($this->actives, $profile);
25
- }
26
-
27
- public function leave(Twig_Profiler_Profile $profile)
28
- {
29
- $profile->leave();
30
- array_shift($this->actives);
31
-
32
- if (1 === count($this->actives)) {
33
- $this->actives[0]->leave();
34
- }
35
- }
36
-
37
- public function getNodeVisitors()
38
- {
39
- return [new Twig_Profiler_NodeVisitor_Profiler(get_class($this))];
40
- }
41
-
42
- public function getName()
43
- {
44
- return 'profiler';
45
  }
46
  }
47
-
48
- class_alias('Twig_Extension_Profiler', 'Twig\Extension\ProfilerExtension', false);
49
- class_exists('Twig_Profiler_Profile');
1
  <?php
2
 
3
+ use Twig\Extension\ProfilerExtension;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Extension\ProfilerExtension');
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Extension_Profiler extends ProfilerExtension
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
 
src/lib/vendor/twig/twig/lib/Twig/Extension/Sandbox.php CHANGED
@@ -1,103 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * @final
14
- */
15
- class Twig_Extension_Sandbox extends Twig_Extension
16
- {
17
- protected $sandboxedGlobally;
18
- protected $sandboxed;
19
- protected $policy;
20
 
21
- public function __construct(Twig_Sandbox_SecurityPolicyInterface $policy, $sandboxed = false)
 
22
  {
23
- $this->policy = $policy;
24
- $this->sandboxedGlobally = $sandboxed;
25
- }
26
-
27
- public function getTokenParsers()
28
- {
29
- return [new Twig_TokenParser_Sandbox()];
30
- }
31
-
32
- public function getNodeVisitors()
33
- {
34
- return [new Twig_NodeVisitor_Sandbox()];
35
- }
36
-
37
- public function enableSandbox()
38
- {
39
- $this->sandboxed = true;
40
- }
41
-
42
- public function disableSandbox()
43
- {
44
- $this->sandboxed = false;
45
- }
46
-
47
- public function isSandboxed()
48
- {
49
- return $this->sandboxedGlobally || $this->sandboxed;
50
- }
51
-
52
- public function isSandboxedGlobally()
53
- {
54
- return $this->sandboxedGlobally;
55
- }
56
-
57
- public function setSecurityPolicy(Twig_Sandbox_SecurityPolicyInterface $policy)
58
- {
59
- $this->policy = $policy;
60
- }
61
-
62
- public function getSecurityPolicy()
63
- {
64
- return $this->policy;
65
- }
66
-
67
- public function checkSecurity($tags, $filters, $functions)
68
- {
69
- if ($this->isSandboxed()) {
70
- $this->policy->checkSecurity($tags, $filters, $functions);
71
- }
72
- }
73
-
74
- public function checkMethodAllowed($obj, $method)
75
- {
76
- if ($this->isSandboxed()) {
77
- $this->policy->checkMethodAllowed($obj, $method);
78
- }
79
- }
80
-
81
- public function checkPropertyAllowed($obj, $method)
82
- {
83
- if ($this->isSandboxed()) {
84
- $this->policy->checkPropertyAllowed($obj, $method);
85
- }
86
- }
87
-
88
- public function ensureToStringAllowed($obj)
89
- {
90
- if ($this->isSandboxed() && is_object($obj)) {
91
- $this->policy->checkMethodAllowed($obj, '__toString');
92
- }
93
-
94
- return $obj;
95
- }
96
-
97
- public function getName()
98
- {
99
- return 'sandbox';
100
  }
101
  }
102
-
103
- class_alias('Twig_Extension_Sandbox', 'Twig\Extension\SandboxExtension', false);
1
  <?php
2
 
3
+ use Twig\Extension\SandboxExtension;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Extension\SandboxExtension');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Extension_Sandbox extends SandboxExtension
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Extension/Staging.php CHANGED
@@ -1,112 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Internal class.
14
- *
15
- * This class is used by Twig_Environment as a staging area and must not be used directly.
16
- *
17
- * @author Fabien Potencier <fabien@symfony.com>
18
- *
19
- * @internal
20
- */
21
- class Twig_Extension_Staging extends Twig_Extension
22
- {
23
- protected $functions = [];
24
- protected $filters = [];
25
- protected $visitors = [];
26
- protected $tokenParsers = [];
27
- protected $globals = [];
28
- protected $tests = [];
29
 
30
- public function addFunction($name, $function)
 
31
  {
32
- if (isset($this->functions[$name])) {
33
- @trigger_error(sprintf('Overriding function "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $name), E_USER_DEPRECATED);
34
- }
35
-
36
- $this->functions[$name] = $function;
37
- }
38
-
39
- public function getFunctions()
40
- {
41
- return $this->functions;
42
- }
43
-
44
- public function addFilter($name, $filter)
45
- {
46
- if (isset($this->filters[$name])) {
47
- @trigger_error(sprintf('Overriding filter "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $name), E_USER_DEPRECATED);
48
- }
49
-
50
- $this->filters[$name] = $filter;
51
- }
52
-
53
- public function getFilters()
54
- {
55
- return $this->filters;
56
- }
57
-
58
- public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
59
- {
60
- $this->visitors[] = $visitor;
61
- }
62
-
63
- public function getNodeVisitors()
64
- {
65
- return $this->visitors;
66
- }
67
-
68
- public function addTokenParser(Twig_TokenParserInterface $parser)
69
- {
70
- if (isset($this->tokenParsers[$parser->getTag()])) {
71
- @trigger_error(sprintf('Overriding tag "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $parser->getTag()), E_USER_DEPRECATED);
72
- }
73
-
74
- $this->tokenParsers[$parser->getTag()] = $parser;
75
- }
76
-
77
- public function getTokenParsers()
78
- {
79
- return $this->tokenParsers;
80
- }
81
-
82
- public function addGlobal($name, $value)
83
- {
84
- $this->globals[$name] = $value;
85
- }
86
-
87
- public function getGlobals()
88
- {
89
- return $this->globals;
90
- }
91
-
92
- public function addTest($name, $test)
93
- {
94
- if (isset($this->tests[$name])) {
95
- @trigger_error(sprintf('Overriding test "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $name), E_USER_DEPRECATED);
96
- }
97
-
98
- $this->tests[$name] = $test;
99
- }
100
-
101
- public function getTests()
102
- {
103
- return $this->tests;
104
- }
105
-
106
- public function getName()
107
- {
108
- return 'staging';
109
  }
110
  }
111
-
112
- class_alias('Twig_Extension_Staging', 'Twig\Extension\StagingExtension', false);
1
  <?php
2
 
3
+ use Twig\Extension\StagingExtension;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Extension\StagingExtension');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Extension_Staging extends StagingExtension
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Extension/StringLoader.php CHANGED
@@ -1,47 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * @final
14
- */
15
- class Twig_Extension_StringLoader extends Twig_Extension
16
- {
17
- public function getFunctions()
18
- {
19
- return [
20
- new Twig_SimpleFunction('template_from_string', 'twig_template_from_string', ['needs_environment' => true]),
21
- ];
22
- }
23
 
24
- public function getName()
 
25
  {
26
- return 'string_loader';
27
  }
28
  }
29
-
30
- /**
31
- * Loads a template from a string.
32
- *
33
- * <pre>
34
- * {{ include(template_from_string("Hello {{ name }}")) }}
35
- * </pre>
36
- *
37
- * @param Twig_Environment $env A Twig_Environment instance
38
- * @param string $template A template as a string or object implementing __toString()
39
- *
40
- * @return Twig_Template
41
- */
42
- function twig_template_from_string(Twig_Environment $env, $template)
43
- {
44
- return $env->createTemplate((string) $template);
45
- }
46
-
47
- class_alias('Twig_Extension_StringLoader', 'Twig\Extension\StringLoaderExtension', false);
1
  <?php
2
 
3
+ use Twig\Extension\StringLoaderExtension;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Extension\StringLoaderExtension');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Extension_StringLoader extends StringLoaderExtension
9
  {
 
10
  }
11
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/lib/vendor/twig/twig/lib/Twig/ExtensionInterface.php CHANGED
@@ -1,90 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Interface implemented by extension classes.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- interface Twig_ExtensionInterface
18
- {
19
- /**
20
- * Initializes the runtime environment.
21
- *
22
- * This is where you can load some file that contains filter functions for instance.
23
- *
24
- * @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead
25
- */
26
- public function initRuntime(Twig_Environment $environment);
27
 
28
- /**
29
- * Returns the token parser instances to add to the existing list.
30
- *
31
- * @return Twig_TokenParserInterface[]
32
- */
33
- public function getTokenParsers();
34
-
35
- /**
36
- * Returns the node visitor instances to add to the existing list.
37
- *
38
- * @return Twig_NodeVisitorInterface[]
39
- */
40
- public function getNodeVisitors();
41
-
42
- /**
43
- * Returns a list of filters to add to the existing list.
44
- *
45
- * @return Twig_SimpleFilter[]
46
- */
47
- public function getFilters();
48
-
49
- /**
50
- * Returns a list of tests to add to the existing list.
51
- *
52
- * @return Twig_SimpleTest[]
53
- */
54
- public function getTests();
55
-
56
- /**
57
- * Returns a list of functions to add to the existing list.
58
- *
59
- * @return Twig_SimpleFunction[]
60
- */
61
- public function getFunctions();
62
-
63
- /**
64
- * Returns a list of operators to add to the existing list.
65
- *
66
- * @return array<array> First array of unary operators, second array of binary operators
67
- */
68
- public function getOperators();
69
-
70
- /**
71
- * Returns a list of global variables to add to the existing list.
72
- *
73
- * @return array An array of global variables
74
- *
75
- * @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_GlobalsInterface instead
76
- */
77
- public function getGlobals();
78
-
79
- /**
80
- * Returns the name of the extension.
81
- *
82
- * @return string The extension name
83
- *
84
- * @deprecated since 1.26 (to be removed in 2.0), not used anymore internally
85
- */
86
- public function getName();
87
  }
88
-
89
- class_alias('Twig_ExtensionInterface', 'Twig\Extension\ExtensionInterface', false);
90
- class_exists('Twig_Environment');
1
  <?php
2
 
3
+ use Twig\Extension\ExtensionInterface;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Extension\ExtensionInterface');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_ExtensionInterface extends ExtensionInterface
9
+ {
10
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  }
 
 
 
src/lib/vendor/twig/twig/lib/Twig/FactoryRuntimeLoader.php CHANGED
@@ -1,39 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Lazy loads the runtime implementations for a Twig element.
14
- *
15
- * @author Robin Chalas <robin.chalas@gmail.com>
16
- */
17
- class Twig_FactoryRuntimeLoader implements Twig_RuntimeLoaderInterface
18
- {
19
- private $map;
20
 
21
- /**
22
- * @param array $map An array where keys are class names and values factory callables
23
- */
24
- public function __construct($map = [])
25
  {
26
- $this->map = $map;
27
- }
28
-
29
- public function load($class)
30
- {
31
- if (isset($this->map[$class])) {
32
- $runtimeFactory = $this->map[$class];
33
-
34
- return $runtimeFactory();
35
- }
36
  }
37
  }
38
-
39
- class_alias('Twig_FactoryRuntimeLoader', 'Twig\RuntimeLoader\FactoryRuntimeLoader', false);
1
  <?php
2
 
3
+ use Twig\RuntimeLoader\FactoryRuntimeLoader;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\RuntimeLoader\FactoryRuntimeLoader');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_FactoryRuntimeLoader extends FactoryRuntimeLoader
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php CHANGED
@@ -1,60 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Default autoescaping strategy based on file names.
14
- *
15
- * This strategy sets the HTML as the default autoescaping strategy,
16
- * but changes it based on the template name.
17
- *
18
- * Note that there is no runtime performance impact as the
19
- * default autoescaping strategy is set at compilation time.
20
- *
21
- * @author Fabien Potencier <fabien@symfony.com>
22
- */
23
- class Twig_FileExtensionEscapingStrategy
24
- {
25
- /**
26
- * Guesses the best autoescaping strategy based on the file name.
27
- *
28
- * @param string $name The template name
29
- *
30
- * @return string|false The escaping strategy name to use or false to disable
31
- */
32
- public static function guess($name)
33
- {
34
- if (in_array(substr($name, -1), ['/', '\\'])) {
35
- return 'html'; // return html for directories
36
- }
37
-
38
- if ('.twig' === substr($name, -5)) {
39
- $name = substr($name, 0, -5);
40
- }
41
-
42
- $extension = pathinfo($name, PATHINFO_EXTENSION);
43
-
44
- switch ($extension) {
45
- case 'js':
46
- return 'js';
47
 
48
- case 'css':
49
- return 'css';
50
-
51
- case 'txt':
52
- return false;
53
-
54
- default:
55
- return 'html';
56
- }
57
  }
58
  }
59
-
60
- class_alias('Twig_FileExtensionEscapingStrategy', 'Twig\FileExtensionEscapingStrategy', false);
1
  <?php
2
 
3
+ use Twig\FileExtensionEscapingStrategy;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\FileExtensionEscapingStrategy');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_FileExtensionEscapingStrategy extends FileExtensionEscapingStrategy
9
+ {
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Filter.php CHANGED
@@ -9,12 +9,14 @@
9
  * file that was distributed with this source code.
10
  */
11
 
12
- @trigger_error('The Twig_Filter class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED);
 
 
13
 
14
  /**
15
  * Represents a template filter.
16
  *
17
- * Use Twig_SimpleFilter instead.
18
  *
19
  * @author Fabien Potencier <fabien@symfony.com>
20
  *
@@ -56,14 +58,14 @@ abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableI
56
  return $this->options['needs_context'];
57
  }
58
 
59
- public function getSafe(Twig_Node $filterArgs)
60
  {
61
  if (isset($this->options['is_safe'])) {
62
  return $this->options['is_safe'];
63
  }
64
 
65
  if (isset($this->options['is_safe_callback'])) {
66
- return call_user_func($this->options['is_safe_callback'], $filterArgs);
67
  }
68
  }
69
 
9
  * file that was distributed with this source code.
10
  */
11
 
12
+ use Twig\Node\Node;
13
+
14
+ @trigger_error('The Twig_Filter class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFilter instead.', E_USER_DEPRECATED);
15
 
16
  /**
17
  * Represents a template filter.
18
  *
19
+ * Use \Twig\TwigFilter instead.
20
  *
21
  * @author Fabien Potencier <fabien@symfony.com>
22
  *
58
  return $this->options['needs_context'];
59
  }
60
 
61
+ public function getSafe(Node $filterArgs)
62
  {
63
  if (isset($this->options['is_safe'])) {
64
  return $this->options['is_safe'];
65
  }
66
 
67
  if (isset($this->options['is_safe_callback'])) {
68
+ return \call_user_func($this->options['is_safe_callback'], $filterArgs);
69
  }
70
  }
71
 
src/lib/vendor/twig/twig/lib/Twig/Filter/Function.php CHANGED
@@ -9,12 +9,12 @@
9
  * file that was distributed with this source code.
10
  */
11
 
12
- @trigger_error('The Twig_Filter_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED);
13
 
14
  /**
15
  * Represents a function template filter.
16
  *
17
- * Use Twig_SimpleFilter instead.
18
  *
19
  * @author Fabien Potencier <fabien@symfony.com>
20
  *
9
  * file that was distributed with this source code.
10
  */
11
 
12
+ @trigger_error('The Twig_Filter_Function class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFilter instead.', E_USER_DEPRECATED);
13
 
14
  /**
15
  * Represents a function template filter.
16
  *
17
+ * Use \Twig\TwigFilter instead.
18
  *
19
  * @author Fabien Potencier <fabien@symfony.com>
20
  *
src/lib/vendor/twig/twig/lib/Twig/Filter/Method.php CHANGED
@@ -9,12 +9,14 @@
9
  * file that was distributed with this source code.
10
  */
11
 
12
- @trigger_error('The Twig_Filter_Method class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED);
 
 
13
 
14
  /**
15
  * Represents a method template filter.
16
  *
17
- * Use Twig_SimpleFilter instead.
18
  *
19
  * @author Fabien Potencier <fabien@symfony.com>
20
  *
@@ -25,7 +27,7 @@ class Twig_Filter_Method extends Twig_Filter
25
  protected $extension;
26
  protected $method;
27
 
28
- public function __construct(Twig_ExtensionInterface $extension, $method, array $options = [])
29
  {
30
  $options['callable'] = [$extension, $method];
31
 
@@ -37,6 +39,6 @@ class Twig_Filter_Method extends Twig_Filter
37
 
38
  public function compile()
39
  {
40
- return sprintf('$this->env->getExtension(\'%s\')->%s', get_class($this->extension), $this->method);
41
  }
42
  }
9
  * file that was distributed with this source code.
10
  */
11
 
12
+ use Twig\Extension\ExtensionInterface;
13
+
14
+ @trigger_error('The Twig_Filter_Method class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFilter instead.', E_USER_DEPRECATED);
15
 
16
  /**
17
  * Represents a method template filter.
18
  *
19
+ * Use \Twig\TwigFilter instead.
20
  *
21
  * @author Fabien Potencier <fabien@symfony.com>
22
  *
27
  protected $extension;
28
  protected $method;
29
 
30
+ public function __construct(ExtensionInterface $extension, $method, array $options = [])
31
  {
32
  $options['callable'] = [$extension, $method];
33
 
39
 
40
  public function compile()
41
  {
42
+ return sprintf('$this->env->getExtension(\'%s\')->%s', \get_class($this->extension), $this->method);
43
  }
44
  }
src/lib/vendor/twig/twig/lib/Twig/Filter/Node.php CHANGED
@@ -9,12 +9,12 @@
9
  * file that was distributed with this source code.
10
  */
11
 
12
- @trigger_error('The Twig_Filter_Node class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED);
13
 
14
  /**
15
  * Represents a template filter as a node.
16
  *
17
- * Use Twig_SimpleFilter instead.
18
  *
19
  * @author Fabien Potencier <fabien@symfony.com>
20
  *
9
  * file that was distributed with this source code.
10
  */
11
 
12
+ @trigger_error('The Twig_Filter_Node class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFilter instead.', E_USER_DEPRECATED);
13
 
14
  /**
15
  * Represents a template filter as a node.
16
  *
17
+ * Use \Twig\TwigFilter instead.
18
  *
19
  * @author Fabien Potencier <fabien@symfony.com>
20
  *
src/lib/vendor/twig/twig/lib/Twig/FilterCallableInterface.php CHANGED
@@ -12,7 +12,7 @@
12
  /**
13
  * Represents a callable template filter.
14
  *
15
- * Use Twig_SimpleFilter instead.
16
  *
17
  * @author Fabien Potencier <fabien@symfony.com>
18
  *
12
  /**
13
  * Represents a callable template filter.
14
  *
15
+ * Use \Twig\TwigFilter instead.
16
  *
17
  * @author Fabien Potencier <fabien@symfony.com>
18
  *
src/lib/vendor/twig/twig/lib/Twig/FilterInterface.php CHANGED
@@ -9,10 +9,12 @@
9
  * file that was distributed with this source code.
10
  */
11
 
 
 
12
  /**
13
  * Represents a template filter.
14
  *
15
- * Use Twig_SimpleFilter instead.
16
  *
17
  * @author Fabien Potencier <fabien@symfony.com>
18
  *
@@ -31,7 +33,7 @@ interface Twig_FilterInterface
31
 
32
  public function needsContext();
33
 
34
- public function getSafe(Twig_Node $filterArgs);
35
 
36
  public function getPreservesSafety();
37
 
9
  * file that was distributed with this source code.
10
  */
11
 
12
+ use Twig\Node\Node;
13
+
14
  /**
15
  * Represents a template filter.
16
  *
17
+ * Use \Twig\TwigFilter instead.
18
  *
19
  * @author Fabien Potencier <fabien@symfony.com>
20
  *
33
 
34
  public function needsContext();
35
 
36
+ public function getSafe(Node $filterArgs);
37
 
38
  public function getPreservesSafety();
39
 
src/lib/vendor/twig/twig/lib/Twig/Function.php CHANGED
@@ -9,12 +9,14 @@
9
  * file that was distributed with this source code.
10
  */
11
 
12
- @trigger_error('The Twig_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED);
 
 
13
 
14
  /**
15
  * Represents a template function.
16
  *
17
- * Use Twig_SimpleFunction instead.
18
  *
19
  * @author Fabien Potencier <fabien@symfony.com>
20
  *
@@ -54,14 +56,14 @@ abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCal
54
  return $this->options['needs_context'];
55
  }
56
 
57
- public function getSafe(Twig_Node $functionArgs)
58
  {
59
  if (isset($this->options['is_safe'])) {
60
  return $this->options['is_safe'];
61
  }
62
 
63
  if (isset($this->options['is_safe_callback'])) {
64
- return call_user_func($this->options['is_safe_callback'], $functionArgs);
65
  }
66
 
67
  return [];
9
  * file that was distributed with this source code.
10
  */
11
 
12
+ use Twig\Node\Node;
13
+
14
+ @trigger_error('The Twig_Function class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFunction instead.', E_USER_DEPRECATED);
15
 
16
  /**
17
  * Represents a template function.
18
  *
19
+ * Use \Twig\TwigFunction instead.
20
  *
21
  * @author Fabien Potencier <fabien@symfony.com>
22
  *
56
  return $this->options['needs_context'];
57
  }
58
 
59
+ public function getSafe(Node $functionArgs)
60
  {
61
  if (isset($this->options['is_safe'])) {
62
  return $this->options['is_safe'];
63
  }
64
 
65
  if (isset($this->options['is_safe_callback'])) {
66
+ return \call_user_func($this->options['is_safe_callback'], $functionArgs);
67
  }
68
 
69
  return [];
src/lib/vendor/twig/twig/lib/Twig/Function/Function.php CHANGED
@@ -10,12 +10,12 @@
10
  * file that was distributed with this source code.
11
  */
12
 
13
- @trigger_error('The Twig_Function_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED);
14
 
15
  /**
16
  * Represents a function template function.
17
  *
18
- * Use Twig_SimpleFunction instead.
19
  *
20
  * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
21
  *
10
  * file that was distributed with this source code.
11
  */
12
 
13
+ @trigger_error('The Twig_Function_Function class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFunction instead.', E_USER_DEPRECATED);
14
 
15
  /**
16
  * Represents a function template function.
17
  *
18
+ * Use \Twig\TwigFunction instead.
19
  *
20
  * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
21
  *
src/lib/vendor/twig/twig/lib/Twig/Function/Method.php CHANGED
@@ -10,12 +10,14 @@
10
  * file that was distributed with this source code.
11
  */
12
 
13
- @trigger_error('The Twig_Function_Method class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED);
 
 
14
 
15
  /**
16
  * Represents a method template function.
17
  *
18
- * Use Twig_SimpleFunction instead.
19
  *
20
  * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
21
  *
@@ -26,7 +28,7 @@ class Twig_Function_Method extends Twig_Function
26
  protected $extension;
27
  protected $method;
28
 
29
- public function __construct(Twig_ExtensionInterface $extension, $method, array $options = [])
30
  {
31
  $options['callable'] = [$extension, $method];
32
 
@@ -38,6 +40,6 @@ class Twig_Function_Method extends Twig_Function
38
 
39
  public function compile()
40
  {
41
- return sprintf('$this->env->getExtension(\'%s\')->%s', get_class($this->extension), $this->method);
42
  }
43
  }
10
  * file that was distributed with this source code.
11
  */
12
 
13
+ use Twig\Extension\ExtensionInterface;
14
+
15
+ @trigger_error('The Twig_Function_Method class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFunction instead.', E_USER_DEPRECATED);
16
 
17
  /**
18
  * Represents a method template function.
19
  *
20
+ * Use \Twig\TwigFunction instead.
21
  *
22
  * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
23
  *
28
  protected $extension;
29
  protected $method;
30
 
31
+ public function __construct(ExtensionInterface $extension, $method, array $options = [])
32
  {
33
  $options['callable'] = [$extension, $method];
34
 
40
 
41
  public function compile()
42
  {
43
+ return sprintf('$this->env->getExtension(\'%s\')->%s', \get_class($this->extension), $this->method);
44
  }
45
  }
src/lib/vendor/twig/twig/lib/Twig/Function/Node.php CHANGED
@@ -9,12 +9,12 @@
9
  * file that was distributed with this source code.
10
  */
11
 
12
- @trigger_error('The Twig_Function_Node class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED);
13
 
14
  /**
15
  * Represents a template function as a node.
16
  *
17
- * Use Twig_SimpleFunction instead.
18
  *
19
  * @author Fabien Potencier <fabien@symfony.com>
20
  *
9
  * file that was distributed with this source code.
10
  */
11
 
12
+ @trigger_error('The Twig_Function_Node class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFunction instead.', E_USER_DEPRECATED);
13
 
14
  /**
15
  * Represents a template function as a node.
16
  *
17
+ * Use \Twig\TwigFunction instead.
18
  *
19
  * @author Fabien Potencier <fabien@symfony.com>
20
  *
src/lib/vendor/twig/twig/lib/Twig/FunctionCallableInterface.php CHANGED
@@ -12,7 +12,7 @@
12
  /**
13
  * Represents a callable template function.
14
  *
15
- * Use Twig_SimpleFunction instead.
16
  *
17
  * @author Fabien Potencier <fabien@symfony.com>
18
  *
12
  /**
13
  * Represents a callable template function.
14
  *
15
+ * Use \Twig\TwigFunction instead.
16
  *
17
  * @author Fabien Potencier <fabien@symfony.com>
18
  *
src/lib/vendor/twig/twig/lib/Twig/FunctionInterface.php CHANGED
@@ -10,10 +10,12 @@
10
  * file that was distributed with this source code.
11
  */
12
 
 
 
13
  /**
14
  * Represents a template function.
15
  *
16
- * Use Twig_SimpleFunction instead.
17
  *
18
  * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
19
  *
@@ -32,7 +34,7 @@ interface Twig_FunctionInterface
32
 
33
  public function needsContext();
34
 
35
- public function getSafe(Twig_Node $filterArgs);
36
 
37
  public function setArguments($arguments);
38
 
10
  * file that was distributed with this source code.
11
  */
12
 
13
+ use Twig\Node\Node;
14
+
15
  /**
16
  * Represents a template function.
17
  *
18
+ * Use \Twig\TwigFunction instead.
19
  *
20
  * @author Arnaud Le Blanc <arnaud.lb@gmail.com>
21
  *
34
 
35
  public function needsContext();
36
 
37
+ public function getSafe(Node $filterArgs);
38
 
39
  public function setArguments($arguments);
40
 
src/lib/vendor/twig/twig/lib/Twig/Lexer.php CHANGED
@@ -1,427 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Lexes a template string.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- class Twig_Lexer implements Twig_LexerInterface
19
- {
20
- protected $tokens;
21
- protected $code;
22
- protected $cursor;
23
- protected $lineno;
24
- protected $end;
25
- protected $state;
26
- protected $states;
27
- protected $brackets;
28
- protected $env;
29
- // to be renamed to $name in 2.0 (where it is private)
30
- protected $filename;
31
- protected $options;
32
- protected $regexes;
33
- protected $position;
34
- protected $positions;
35
- protected $currentVarBlockLine;
36
 
37
- private $source;
38
-
39
- const STATE_DATA = 0;
40
- const STATE_BLOCK = 1;
41
- const STATE_VAR = 2;
42
- const STATE_STRING = 3;
43
- const STATE_INTERPOLATION = 4;
44
-
45
- const REGEX_NAME = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A';
46
- const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A';
47
- const REGEX_STRING = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As';
48
- const REGEX_DQ_STRING_DELIM = '/"/A';
49
- const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As';
50
- const PUNCTUATION = '()[]{}?:.,|';
51
-
52
- public function __construct(Twig_Environment $env, array $options = [])
53
- {
54
- $this->env = $env;
55
-
56
- $this->options = array_merge([
57
- 'tag_comment' => ['{#', '#}'],
58
- 'tag_block' => ['{%', '%}'],
59
- 'tag_variable' => ['{{', '}}'],
60
- 'whitespace_trim' => '-',
61
- 'interpolation' => ['#{', '}'],
62
- ], $options);
63
-
64
- $this->regexes = [
65
- 'lex_var' => '/\s*'.preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_variable'][1], '/').'/A',
66
- 'lex_block' => '/\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')\n?/A',
67
- 'lex_raw_data' => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*(?:end%s)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s',
68
- 'operator' => $this->getOperatorRegex(),
69
- 'lex_comment' => '/(?:'.preg_quote($this->options['whitespace_trim'], '/').preg_quote($this->options['tag_comment'][1], '/').'\s*|'.preg_quote($this->options['tag_comment'][1], '/').')\n?/s',
70
- 'lex_block_raw' => '/\s*(raw|verbatim)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As',
71
- 'lex_block_line' => '/\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '/').'/As',
72
- 'lex_tokens_start' => '/('.preg_quote($this->options['tag_variable'][0], '/').'|'.preg_quote($this->options['tag_block'][0], '/').'|'.preg_quote($this->options['tag_comment'][0], '/').')('.preg_quote($this->options['whitespace_trim'], '/').')?/s',
73
- 'interpolation_start' => '/'.preg_quote($this->options['interpolation'][0], '/').'\s*/A',
74
- 'interpolation_end' => '/\s*'.preg_quote($this->options['interpolation'][1], '/').'/A',
75
- ];
76
- }
77
-
78
- public function tokenize($code, $name = null)
79
- {
80
- if (!$code instanceof Twig_Source) {
81
- @trigger_error(sprintf('Passing a string as the $code argument of %s() is deprecated since version 1.27 and will be removed in 2.0. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED);
82
- $this->source = new Twig_Source($code, $name);
83
- } else {
84
- $this->source = $code;
85
- }
86
-
87
- if (((int) ini_get('mbstring.func_overload')) & 2) {
88
- @trigger_error('Support for having "mbstring.func_overload" different from 0 is deprecated version 1.29 and will be removed in 2.0.', E_USER_DEPRECATED);
89
- }
90
-
91
- if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
92
- $mbEncoding = mb_internal_encoding();
93
- mb_internal_encoding('ASCII');
94
- } else {
95
- $mbEncoding = null;
96
- }
97
-
98
- $this->code = str_replace(["\r\n", "\r"], "\n", $this->source->getCode());
99
- $this->filename = $this->source->getName();
100
- $this->cursor = 0;
101
- $this->lineno = 1;
102
- $this->end = strlen($this->code);
103
- $this->tokens = [];
104
- $this->state = self::STATE_DATA;
105
- $this->states = [];
106
- $this->brackets = [];
107
- $this->position = -1;
108
-
109
- // find all token starts in one go
110
- preg_match_all($this->regexes['lex_tokens_start'], $this->code, $matches, PREG_OFFSET_CAPTURE);
111
- $this->positions = $matches;
112
-
113
- while ($this->cursor < $this->end) {
114
- // dispatch to the lexing functions depending
115
- // on the current state
116
- switch ($this->state) {
117
- case self::STATE_DATA:
118
- $this->lexData();
119
- break;
120
-
121
- case self::STATE_BLOCK:
122
- $this->lexBlock();
123
- break;
124
-
125
- case self::STATE_VAR:
126
- $this->lexVar();
127
- break;
128
-
129
- case self::STATE_STRING:
130
- $this->lexString();
131
- break;
132
-
133
- case self::STATE_INTERPOLATION:
134
- $this->lexInterpolation();
135
- break;
136
- }
137
- }
138
-
139
- $this->pushToken(Twig_Token::EOF_TYPE);
140
-
141
- if (!empty($this->brackets)) {
142
- list($expect, $lineno) = array_pop($this->brackets);
143
- throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $expect), $lineno, $this->source);
144
- }
145
-
146
- if ($mbEncoding) {
147
- mb_internal_encoding($mbEncoding);
148
- }
149
-
150
- return new Twig_TokenStream($this->tokens, $this->source);
151
- }
152
-
153
- protected function lexData()
154
- {
155
- // if no matches are left we return the rest of the template as simple text token
156
- if ($this->position == count($this->positions[0]) - 1) {
157
- $this->pushToken(Twig_Token::TEXT_TYPE, substr($this->code, $this->cursor));
158
- $this->cursor = $this->end;
159
-
160
- return;
161
- }
162
-
163
- // Find the first token after the current cursor
164
- $position = $this->positions[0][++$this->position];
165
- while ($position[1] < $this->cursor) {
166
- if ($this->position == count($this->positions[0]) - 1) {
167
- return;
168
- }
169
- $position = $this->positions[0][++$this->position];
170
- }
171
-
172
- // push the template text first
173
- $text = $textContent = substr($this->code, $this->cursor, $position[1] - $this->cursor);
174
- if (isset($this->positions[2][$this->position][0])) {
175
- $text = rtrim($text);
176
- }
177
- $this->pushToken(Twig_Token::TEXT_TYPE, $text);
178
- $this->moveCursor($textContent.$position[0]);
179
-
180
- switch ($this->positions[1][$this->position][0]) {
181
- case $this->options['tag_comment'][0]:
182
- $this->lexComment();
183
- break;
184
-
185
- case $this->options['tag_block'][0]:
186
- // raw data?
187
- if (preg_match($this->regexes['lex_block_raw'], $this->code, $match, null, $this->cursor)) {
188
- $this->moveCursor($match[0]);
189
- $this->lexRawData($match[1]);
190
- // {% line \d+ %}
191
- } elseif (preg_match($this->regexes['lex_block_line'], $this->code, $match, null, $this->cursor)) {
192
- $this->moveCursor($match[0]);
193
- $this->lineno = (int) $match[1];
194
- } else {
195
- $this->pushToken(Twig_Token::BLOCK_START_TYPE);
196
- $this->pushState(self::STATE_BLOCK);
197
- $this->currentVarBlockLine = $this->lineno;
198
- }
199
- break;
200
-
201
- case $this->options['tag_variable'][0]:
202
- $this->pushToken(Twig_Token::VAR_START_TYPE);
203
- $this->pushState(self::STATE_VAR);
204
- $this->currentVarBlockLine = $this->lineno;
205
- break;
206
- }
207
- }
208
-
209
- protected function lexBlock()
210
- {
211
- if (empty($this->brackets) && preg_match($this->regexes['lex_block'], $this->code, $match, null, $this->cursor)) {
212
- $this->pushToken(Twig_Token::BLOCK_END_TYPE);
213
- $this->moveCursor($match[0]);
214
- $this->popState();
215
- } else {
216
- $this->lexExpression();
217
- }
218
- }
219
-
220
- protected function lexVar()
221
- {
222
- if (empty($this->brackets) && preg_match($this->regexes['lex_var'], $this->code, $match, null, $this->cursor)) {
223
- $this->pushToken(Twig_Token::VAR_END_TYPE);
224
- $this->moveCursor($match[0]);
225
- $this->popState();
226
- } else {
227
- $this->lexExpression();
228
- }
229
- }
230
-
231
- protected function lexExpression()
232
- {
233
- // whitespace
234
- if (preg_match('/\s+/A', $this->code, $match, null, $this->cursor)) {
235
- $this->moveCursor($match[0]);
236
-
237
- if ($this->cursor >= $this->end) {
238
- throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', self::STATE_BLOCK === $this->state ? 'block' : 'variable'), $this->currentVarBlockLine, $this->source);
239
- }
240
- }
241
-
242
- // operators
243
- if (preg_match($this->regexes['operator'], $this->code, $match, null, $this->cursor)) {
244
- $this->pushToken(Twig_Token::OPERATOR_TYPE, preg_replace('/\s+/', ' ', $match[0]));
245
- $this->moveCursor($match[0]);
246
- }
247
- // names
248
- elseif (preg_match(self::REGEX_NAME, $this->code, $match, null, $this->cursor)) {
249
- $this->pushToken(Twig_Token::NAME_TYPE, $match[0]);
250
- $this->moveCursor($match[0]);
251
- }
252
- // numbers
253
- elseif (preg_match(self::REGEX_NUMBER, $this->code, $match, null, $this->cursor)) {
254
- $number = (float) $match[0]; // floats
255
- if (ctype_digit($match[0]) && $number <= PHP_INT_MAX) {
256
- $number = (int) $match[0]; // integers lower than the maximum
257
- }
258
- $this->pushToken(Twig_Token::NUMBER_TYPE, $number);
259
- $this->moveCursor($match[0]);
260
- }
261
- // punctuation
262
- elseif (false !== strpos(self::PUNCTUATION, $this->code[$this->cursor])) {
263
- // opening bracket
264
- if (false !== strpos('([{', $this->code[$this->cursor])) {
265
- $this->brackets[] = [$this->code[$this->cursor], $this->lineno];
266
- }
267
- // closing bracket
268
- elseif (false !== strpos(')]}', $this->code[$this->cursor])) {
269
- if (empty($this->brackets)) {
270
- throw new Twig_Error_Syntax(sprintf('Unexpected "%s".', $this->code[$this->cursor]), $this->lineno, $this->source);
271
- }
272
-
273
- list($expect, $lineno) = array_pop($this->brackets);
274
- if ($this->code[$this->cursor] != strtr($expect, '([{', ')]}')) {
275
- throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $expect), $lineno, $this->source);
276
- }
277
- }
278
-
279
- $this->pushToken(Twig_Token::PUNCTUATION_TYPE, $this->code[$this->cursor]);
280
- ++$this->cursor;
281
- }
282
- // strings
283
- elseif (preg_match(self::REGEX_STRING, $this->code, $match, null, $this->cursor)) {
284
- $this->pushToken(Twig_Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1)));
285
- $this->moveCursor($match[0]);
286
- }
287
- // opening double quoted string
288
- elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) {
289
- $this->brackets[] = ['"', $this->lineno];
290
- $this->pushState(self::STATE_STRING);
291
- $this->moveCursor($match[0]);
292
- }
293
- // unlexable
294
- else {
295
- throw new Twig_Error_Syntax(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source);
296
- }
297
- }
298
-
299
- protected function lexRawData($tag)
300
- {
301
- if ('raw' === $tag) {
302
- @trigger_error(sprintf('Twig Tag "raw" is deprecated since version 1.21. Use "verbatim" instead in %s at line %d.', $this->filename, $this->lineno), E_USER_DEPRECATED);
303
- }
304
-
305
- if (!preg_match(str_replace('%s', $tag, $this->regexes['lex_raw_data']), $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
306
- throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "%s" block.', $tag), $this->lineno, $this->source);
307
- }
308
-
309
- $text = substr($this->code, $this->cursor, $match[0][1] - $this->cursor);
310
- $this->moveCursor($text.$match[0][0]);
311
-
312
- if (false !== strpos($match[1][0], $this->options['whitespace_trim'])) {
313
- $text = rtrim($text);
314
- }
315
-
316
- $this->pushToken(Twig_Token::TEXT_TYPE, $text);
317
- }
318
-
319
- protected function lexComment()
320
- {
321
- if (!preg_match($this->regexes['lex_comment'], $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
322
- throw new Twig_Error_Syntax('Unclosed comment.', $this->lineno, $this->source);
323
- }
324
-
325
- $this->moveCursor(substr($this->code, $this->cursor, $match[0][1] - $this->cursor).$match[0][0]);
326
- }
327
-
328
- protected function lexString()
329
- {
330
- if (preg_match($this->regexes['interpolation_start'], $this->code, $match, null, $this->cursor)) {
331
- $this->brackets[] = [$this->options['interpolation'][0], $this->lineno];
332
- $this->pushToken(Twig_Token::INTERPOLATION_START_TYPE);
333
- $this->moveCursor($match[0]);
334
- $this->pushState(self::STATE_INTERPOLATION);
335
- } elseif (preg_match(self::REGEX_DQ_STRING_PART, $this->code, $match, null, $this->cursor) && strlen($match[0]) > 0) {
336
- $this->pushToken(Twig_Token::STRING_TYPE, stripcslashes($match[0]));
337
- $this->moveCursor($match[0]);
338
- } elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) {
339
- list($expect, $lineno) = array_pop($this->brackets);
340
- if ('"' != $this->code[$this->cursor]) {
341
- throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $expect), $lineno, $this->source);
342
- }
343
-
344
- $this->popState();
345
- ++$this->cursor;
346
- } else {
347
- // unlexable
348
- throw new Twig_Error_Syntax(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source);
349
- }
350
- }
351
-
352
- protected function lexInterpolation()
353
- {
354
- $bracket = end($this->brackets);
355
- if ($this->options['interpolation'][0] === $bracket[0] && preg_match($this->regexes['interpolation_end'], $this->code, $match, null, $this->cursor)) {
356
- array_pop($this->brackets);
357
- $this->pushToken(Twig_Token::INTERPOLATION_END_TYPE);
358
- $this->moveCursor($match[0]);
359
- $this->popState();
360
- } else {
361
- $this->lexExpression();
362
- }
363
- }
364
-
365
- protected function pushToken($type, $value = '')
366
- {
367
- // do not push empty text tokens
368
- if (Twig_Token::TEXT_TYPE === $type && '' === $value) {
369
- return;
370
- }
371
-
372
- $this->tokens[] = new Twig_Token($type, $value, $this->lineno);
373
- }
374
-
375
- protected function moveCursor($text)
376
  {
377
- $this->cursor += strlen($text);
378
- $this->lineno += substr_count($text, "\n");
379
- }
380
-
381
- protected function getOperatorRegex()
382
- {
383
- $operators = array_merge(
384
- ['='],
385
- array_keys($this->env->getUnaryOperators()),
386
- array_keys($this->env->getBinaryOperators())
387
- );
388
-
389
- $operators = array_combine($operators, array_map('strlen', $operators));
390
- arsort($operators);
391
-
392
- $regex = [];
393
- foreach ($operators as $operator => $length) {
394
- // an operator that ends with a character must be followed by
395
- // a whitespace or a parenthesis
396
- if (ctype_alpha($operator[$length - 1])) {
397
- $r = preg_quote($operator, '/').'(?=[\s()])';
398
- } else {
399
- $r = preg_quote($operator, '/');
400
- }
401
-
402
- // an operator with a space can be any amount of whitespaces
403
- $r = preg_replace('/\s+/', '\s+', $r);
404
-
405
- $regex[] = $r;
406
- }
407
-
408
- return '/'.implode('|', $regex).'/A';
409
- }
410
-
411
- protected function pushState($state)
412
- {
413
- $this->states[] = $this->state;
414
- $this->state = $state;
415
- }
416
-
417
- protected function popState()
418
- {
419
- if (0 === count($this->states)) {
420
- throw new Exception('Cannot pop state without a previous state.');
421
- }
422
-
423
- $this->state = array_pop($this->states);
424
  }
425
  }
426
-
427
- class_alias('Twig_Lexer', 'Twig\Lexer', false);
1
  <?php
2
 
3
+ use Twig\Lexer;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Lexer');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Lexer extends Lexer
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/LexerInterface.php CHANGED
@@ -9,6 +9,10 @@
9
  * file that was distributed with this source code.
10
  */
11
 
 
 
 
 
12
  /**
13
  * Interface implemented by lexer classes.
14
  *
@@ -21,12 +25,12 @@ interface Twig_LexerInterface
21
  /**
22
  * Tokenizes a source code.
23
  *
24
- * @param string|Twig_Source $code The source code
25
- * @param string $name A unique identifier for the source code
26
  *
27
- * @return Twig_TokenStream
28
  *
29
- * @throws Twig_Error_Syntax When the code is syntactically wrong
30
  */
31
  public function tokenize($code, $name = null);
32
  }
9
  * file that was distributed with this source code.
10
  */
11
 
12
+ use Twig\Error\SyntaxError;
13
+ use Twig\Source;
14
+ use Twig\TokenStream;
15
+
16
  /**
17
  * Interface implemented by lexer classes.
18
  *
25
  /**
26
  * Tokenizes a source code.
27
  *
28
+ * @param string|Source $code The source code
29
+ * @param string $name A unique identifier for the source code
30
  *
31
+ * @return TokenStream
32
  *
33
+ * @throws SyntaxError When the code is syntactically wrong
34
  */
35
  public function tokenize($code, $name = null);
36
  }
src/lib/vendor/twig/twig/lib/Twig/Loader/Array.php CHANGED
@@ -1,97 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Loads a template from an array.
14
- *
15
- * When using this loader with a cache mechanism, you should know that a new cache
16
- * key is generated each time a template content "changes" (the cache key being the
17
- * source code of the template). If you don't want to see your cache grows out of
18
- * control, you need to take care of clearing the old cache file by yourself.
19
- *
20
- * This loader should only be used for unit testing.
21
- *
22
- * @final
23
- *
24
- * @author Fabien Potencier <fabien@symfony.com>
25
- */
26
- class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
27
- {
28
- protected $templates = [];
29
 
30
- /**
31
- * @param array $templates An array of templates (keys are the names, and values are the source code)
32
- */
33
- public function __construct(array $templates = [])
34
  {
35
- $this->templates = $templates;
36
- }
37
-
38
- /**
39
- * Adds or overrides a template.
40
- *
41
- * @param string $name The template name
42
- * @param string $template The template source
43
- */
44
- public function setTemplate($name, $template)
45
- {
46
- $this->templates[(string) $name] = $template;
47
- }
48
-
49
- public function getSource($name)
50
- {
51
- @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
52
-
53
- $name = (string) $name;
54
- if (!isset($this->templates[$name])) {
55
- throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
56
- }
57
-
58
- return $this->templates[$name];
59
- }
60
-
61
- public function getSourceContext($name)
62
- {
63
- $name = (string) $name;
64
- if (!isset($this->templates[$name])) {
65
- throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
66
- }
67
-
68
- return new Twig_Source($this->templates[$name], $name);
69
- }
70
-
71
- public function exists($name)
72
- {
73
- return isset($this->templates[(string) $name]);
74
- }
75
-
76
- public function getCacheKey($name)
77
- {
78
- $name = (string) $name;
79
- if (!isset($this->templates[$name])) {
80
- throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
81
- }
82
-
83
- return $name.':'.$this->templates[$name];
84
- }
85
-
86
- public function isFresh($name, $time)
87
- {
88
- $name = (string) $name;
89
- if (!isset($this->templates[$name])) {
90
- throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name));
91
- }
92
-
93
- return true;
94
  }
95
  }
96
-
97
- class_alias('Twig_Loader_Array', 'Twig\Loader\ArrayLoader', false);
1
  <?php
2
 
3
+ use Twig\Loader\ArrayLoader;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Loader\ArrayLoader');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Loader_Array extends ArrayLoader
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Loader/Chain.php CHANGED
@@ -1,151 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Loads templates from other loaders.
14
- *
15
- * @final
16
- *
17
- * @author Fabien Potencier <fabien@symfony.com>
18
- */
19
- class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
20
- {
21
- private $hasSourceCache = [];
22
- protected $loaders = [];
23
 
24
- /**
25
- * @param Twig_LoaderInterface[] $loaders
26
- */
27
- public function __construct(array $loaders = [])
28
  {
29
- foreach ($loaders as $loader) {
30
- $this->addLoader($loader);
31
- }
32
- }
33
-
34
- public function addLoader(Twig_LoaderInterface $loader)
35
- {
36
- $this->loaders[] = $loader;
37
- $this->hasSourceCache = [];
38
- }
39
-
40
- public function getSource($name)
41
- {
42
- @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
43
-
44
- $exceptions = [];
45
- foreach ($this->loaders as $loader) {
46
- if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
47
- continue;
48
- }
49
-
50
- try {
51
- return $loader->getSource($name);
52
- } catch (Twig_Error_Loader $e) {
53
- $exceptions[] = $e->getMessage();
54
- }
55
- }
56
-
57
- throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
58
- }
59
-
60
- public function getSourceContext($name)
61
- {
62
- $exceptions = [];
63
- foreach ($this->loaders as $loader) {
64
- if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
65
- continue;
66
- }
67
-
68
- try {
69
- if ($loader instanceof Twig_SourceContextLoaderInterface) {
70
- return $loader->getSourceContext($name);
71
- }
72
-
73
- return new Twig_Source($loader->getSource($name), $name);
74
- } catch (Twig_Error_Loader $e) {
75
- $exceptions[] = $e->getMessage();
76
- }
77
- }
78
-
79
- throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
80
- }
81
-
82
- public function exists($name)
83
- {
84
- $name = (string) $name;
85
-
86
- if (isset($this->hasSourceCache[$name])) {
87
- return $this->hasSourceCache[$name];
88
- }
89
-
90
- foreach ($this->loaders as $loader) {
91
- if ($loader instanceof Twig_ExistsLoaderInterface) {
92
- if ($loader->exists($name)) {
93
- return $this->hasSourceCache[$name] = true;
94
- }
95
-
96
- continue;
97
- }
98
-
99
- try {
100
- if ($loader instanceof Twig_SourceContextLoaderInterface) {
101
- $loader->getSourceContext($name);
102
- } else {
103
- $loader->getSource($name);
104
- }
105
-
106
- return $this->hasSourceCache[$name] = true;
107
- } catch (Twig_Error_Loader $e) {
108
- }
109
- }
110
-
111
- return $this->hasSourceCache[$name] = false;
112
- }
113
-
114
- public function getCacheKey($name)
115
- {
116
- $exceptions = [];
117
- foreach ($this->loaders as $loader) {
118
- if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
119
- continue;
120
- }
121
-
122
- try {
123
- return $loader->getCacheKey($name);
124
- } catch (Twig_Error_Loader $e) {
125
- $exceptions[] = get_class($loader).': '.$e->getMessage();
126
- }
127
- }
128
-
129
- throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
130
- }
131
-
132
- public function isFresh($name, $time)
133
- {
134
- $exceptions = [];
135
- foreach ($this->loaders as $loader) {
136
- if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
137
- continue;
138
- }
139
-
140
- try {
141
- return $loader->isFresh($name, $time);
142
- } catch (Twig_Error_Loader $e) {
143
- $exceptions[] = get_class($loader).': '.$e->getMessage();
144
- }
145
- }
146
-
147
- throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
148
  }
149
  }
150
-
151
- class_alias('Twig_Loader_Chain', 'Twig\Loader\ChainLoader', false);
1
  <?php
2
 
3
+ use Twig\Loader\ChainLoader;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Loader\ChainLoader');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Loader_Chain extends ChainLoader
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Loader/Filesystem.php CHANGED
@@ -1,298 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Loads template from the filesystem.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
18
- {
19
- /** Identifier of the main namespace. */
20
- const MAIN_NAMESPACE = '__main__';
21
 
22
- protected $paths = [];
23
- protected $cache = [];
24
- protected $errorCache = [];
25
-
26
- private $rootPath;
27
-
28
- /**
29
- * @param string|array $paths A path or an array of paths where to look for templates
30
- * @param string|null $rootPath The root path common to all relative paths (null for getcwd())
31
- */
32
- public function __construct($paths = [], $rootPath = null)
33
- {
34
- $this->rootPath = (null === $rootPath ? getcwd() : $rootPath).DIRECTORY_SEPARATOR;
35
- if (false !== $realPath = realpath($rootPath)) {
36
- $this->rootPath = $realPath.DIRECTORY_SEPARATOR;
37
- }
38
-
39
- if ($paths) {
40
- $this->setPaths($paths);
41
- }
42
- }
43
-
44
- /**
45
- * Returns the paths to the templates.
46
- *
47
- * @param string $namespace A path namespace
48
- *
49
- * @return array The array of paths where to look for templates
50
- */
51
- public function getPaths($namespace = self::MAIN_NAMESPACE)
52
  {
53
- return isset($this->paths[$namespace]) ? $this->paths[$namespace] : [];
54
- }
55
-
56
- /**
57
- * Returns the path namespaces.
58
- *
59
- * The main namespace is always defined.
60
- *
61
- * @return array The array of defined namespaces
62
- */
63
- public function getNamespaces()
64
- {
65
- return array_keys($this->paths);
66
- }
67
-
68
- /**
69
- * Sets the paths where templates are stored.
70
- *
71
- * @param string|array $paths A path or an array of paths where to look for templates
72
- * @param string $namespace A path namespace
73
- */
74
- public function setPaths($paths, $namespace = self::MAIN_NAMESPACE)
75
- {
76
- if (!is_array($paths)) {
77
- $paths = [$paths];
78
- }
79
-
80
- $this->paths[$namespace] = [];
81
- foreach ($paths as $path) {
82
- $this->addPath($path, $namespace);
83
- }
84
- }
85
-
86
- /**
87
- * Adds a path where templates are stored.
88
- *
89
- * @param string $path A path where to look for templates
90
- * @param string $namespace A path namespace
91
- *
92
- * @throws Twig_Error_Loader
93
- */
94
- public function addPath($path, $namespace = self::MAIN_NAMESPACE)
95
- {
96
- // invalidate the cache
97
- $this->cache = $this->errorCache = [];
98
-
99
- $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path;
100
- if (!is_dir($checkPath)) {
101
- throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath));
102
- }
103
-
104
- $this->paths[$namespace][] = rtrim($path, '/\\');
105
- }
106
-
107
- /**
108
- * Prepends a path where templates are stored.
109
- *
110
- * @param string $path A path where to look for templates
111
- * @param string $namespace A path namespace
112
- *
113
- * @throws Twig_Error_Loader
114
- */
115
- public function prependPath($path, $namespace = self::MAIN_NAMESPACE)
116
- {
117
- // invalidate the cache
118
- $this->cache = $this->errorCache = [];
119
-
120
- $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path;
121
- if (!is_dir($checkPath)) {
122
- throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath));
123
- }
124
-
125
- $path = rtrim($path, '/\\');
126
-
127
- if (!isset($this->paths[$namespace])) {
128
- $this->paths[$namespace][] = $path;
129
- } else {
130
- array_unshift($this->paths[$namespace], $path);
131
- }
132
- }
133
-
134
- public function getSource($name)
135
- {
136
- @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
137
-
138
- return file_get_contents($this->findTemplate($name));
139
- }
140
-
141
- public function getSourceContext($name)
142
- {
143
- $path = $this->findTemplate($name);
144
-
145
- return new Twig_Source(file_get_contents($path), $name, $path);
146
- }
147
-
148
- public function getCacheKey($name)
149
- {
150
- $path = $this->findTemplate($name);
151
- $len = strlen($this->rootPath);
152
- if (0 === strncmp($this->rootPath, $path, $len)) {
153
- return substr($path, $len);
154
- }
155
-
156
- return $path;
157
- }
158
-
159
- public function exists($name)
160
- {
161
- $name = $this->normalizeName($name);
162
-
163
- if (isset($this->cache[$name])) {
164
- return true;
165
- }
166
-
167
- try {
168
- return false !== $this->findTemplate($name, false);
169
- } catch (Twig_Error_Loader $exception) {
170
- @trigger_error(sprintf('In %s::findTemplate(), you must accept a second argument that when set to "false" returns "false" instead of throwing an exception. Not supporting this argument is deprecated since version 1.27.', get_class($this)), E_USER_DEPRECATED);
171
-
172
- return false;
173
- }
174
- }
175
-
176
- public function isFresh($name, $time)
177
- {
178
- return filemtime($this->findTemplate($name)) < $time;
179
- }
180
-
181
- protected function findTemplate($name)
182
- {
183
- $throw = func_num_args() > 1 ? func_get_arg(1) : true;
184
- $name = $this->normalizeName($name);
185
-
186
- if (isset($this->cache[$name])) {
187
- return $this->cache[$name];
188
- }
189
-
190
- if (isset($this->errorCache[$name])) {
191
- if (!$throw) {
192
- return false;
193
- }
194
-
195
- throw new Twig_Error_Loader($this->errorCache[$name]);
196
- }
197
-
198
- try {
199
- $this->validateName($name);
200
-
201
- list($namespace, $shortname) = $this->parseName($name);
202
- } catch (Twig_Error_Loader $e) {
203
- if (!$throw) {
204
- return false;
205
- }
206
-
207
- throw $e;
208
- }
209
-
210
- if (!isset($this->paths[$namespace])) {
211
- $this->errorCache[$name] = sprintf('There are no registered paths for namespace "%s".', $namespace);
212
-
213
- if (!$throw) {
214
- return false;
215
- }
216
-
217
- throw new Twig_Error_Loader($this->errorCache[$name]);
218
- }
219
-
220
- foreach ($this->paths[$namespace] as $path) {
221
- if (!$this->isAbsolutePath($path)) {
222
- $path = $this->rootPath.'/'.$path;
223
- }
224
-
225
- if (is_file($path.'/'.$shortname)) {
226
- if (false !== $realpath = realpath($path.'/'.$shortname)) {
227
- return $this->cache[$name] = $realpath;
228
- }
229
-
230
- return $this->cache[$name] = $path.'/'.$shortname;
231
- }
232
- }
233
-
234
- $this->errorCache[$name] = sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace]));
235
-
236
- if (!$throw) {
237
- return false;
238
- }
239
-
240
- throw new Twig_Error_Loader($this->errorCache[$name]);
241
- }
242
-
243
- protected function parseName($name, $default = self::MAIN_NAMESPACE)
244
- {
245
- if (isset($name[0]) && '@' == $name[0]) {
246
- if (false === $pos = strpos($name, '/')) {
247
- throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
248
- }
249
-
250
- $namespace = substr($name, 1, $pos - 1);
251
- $shortname = substr($name, $pos + 1);
252
-
253
- return [$namespace, $shortname];
254
- }
255
-
256
- return [$default, $name];
257
- }
258
-
259
- protected function normalizeName($name)
260
- {
261
- return preg_replace('#/{2,}#', '/', str_replace('\\', '/', (string) $name));
262
- }
263
-
264
- protected function validateName($name)
265
- {
266
- if (false !== strpos($name, "\0")) {
267
- throw new Twig_Error_Loader('A template name cannot contain NUL bytes.');
268
- }
269
-
270
- $name = ltrim($name, '/');
271
- $parts = explode('/', $name);
272
- $level = 0;
273
- foreach ($parts as $part) {
274
- if ('..' === $part) {
275
- --$level;
276
- } elseif ('.' !== $part) {
277
- ++$level;
278
- }
279
-
280
- if ($level < 0) {
281
- throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name));
282
- }
283
- }
284
- }
285
-
286
- private function isAbsolutePath($file)
287
- {
288
- return strspn($file, '/\\', 0, 1)
289
- || (strlen($file) > 3 && ctype_alpha($file[0])
290
- && ':' === substr($file, 1, 1)
291
- && strspn($file, '/\\', 2, 1)
292
- )
293
- || null !== parse_url($file, PHP_URL_SCHEME)
294
- ;
295
  }
296
  }
297
-
298
- class_alias('Twig_Loader_Filesystem', 'Twig\Loader\FilesystemLoader', false);
1
  <?php
2
 
3
+ use Twig\Loader\FilesystemLoader;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Loader\FilesystemLoader');
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Loader_Filesystem extends FilesystemLoader
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Loader/String.php CHANGED
@@ -9,7 +9,12 @@
9
  * file that was distributed with this source code.
10
  */
11
 
12
- @trigger_error('The Twig_Loader_String class is deprecated since version 1.18.1 and will be removed in 2.0. Use Twig_Loader_Array instead or Twig_Environment::createTemplate().', E_USER_DEPRECATED);
 
 
 
 
 
13
 
14
  /**
15
  * Loads a template from a string.
@@ -27,18 +32,18 @@
27
  *
28
  * @author Fabien Potencier <fabien@symfony.com>
29
  */
30
- class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
31
  {
32
  public function getSource($name)
33
  {
34
- @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED);
35
 
36
  return $name;
37
  }
38
 
39
  public function getSourceContext($name)
40
  {
41
- return new Twig_Source($name, $name);
42
  }
43
 
44
  public function exists($name)
9
  * file that was distributed with this source code.
10
  */
11
 
12
+ use Twig\Loader\ExistsLoaderInterface;
13
+ use Twig\Loader\LoaderInterface;
14
+ use Twig\Loader\SourceContextLoaderInterface;
15
+ use Twig\Source;
16
+
17
+ @trigger_error('The Twig_Loader_String class is deprecated since version 1.18.1 and will be removed in 2.0. Use "Twig\Loader\ArrayLoader" instead or "Twig\Environment::createTemplate()".', E_USER_DEPRECATED);
18
 
19
  /**
20
  * Loads a template from a string.
32
  *
33
  * @author Fabien Potencier <fabien@symfony.com>
34
  */
35
+ class Twig_Loader_String implements LoaderInterface, ExistsLoaderInterface, SourceContextLoaderInterface
36
  {
37
  public function getSource($name)
38
  {
39
+ @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', \get_class($this)), E_USER_DEPRECATED);
40
 
41
  return $name;
42
  }
43
 
44
  public function getSourceContext($name)
45
  {
46
+ return new Source($name, $name);
47
  }
48
 
49
  public function exists($name)
src/lib/vendor/twig/twig/lib/Twig/LoaderInterface.php CHANGED
@@ -1,57 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Interface all loaders must implement.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- interface Twig_LoaderInterface
18
- {
19
- /**
20
- * Gets the source code of a template, given its name.
21
- *
22
- * @param string $name The name of the template to load
23
- *
24
- * @return string The template source code
25
- *
26
- * @throws Twig_Error_Loader When $name is not found
27
- *
28
- * @deprecated since 1.27 (to be removed in 2.0), implement Twig_SourceContextLoaderInterface
29
- */
30
- public function getSource($name);
31
 
32
- /**
33
- * Gets the cache key to use for the cache for a given template name.
34
- *
35
- * @param string $name The name of the template to load
36
- *
37
- * @return string The cache key
38
- *
39
- * @throws Twig_Error_Loader When $name is not found
40
- */
41
- public function getCacheKey($name);
42
-
43
- /**
44
- * Returns true if the template is still fresh.
45
- *
46
- * @param string $name The template name
47
- * @param int $time Timestamp of the last modification time of the
48
- * cached template
49
- *
50
- * @return bool true if the template is fresh, false otherwise
51
- *
52
- * @throws Twig_Error_Loader When $name is not found
53
- */
54
- public function isFresh($name, $time);
55
  }
56
-
57
- class_alias('Twig_LoaderInterface', 'Twig\Loader\LoaderInterface', false);
1
  <?php
2
 
3
+ use Twig\Loader\LoaderInterface;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Loader\LoaderInterface');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_LoaderInterface extends LoaderInterface
9
+ {
10
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Markup.php CHANGED
@@ -1,39 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Marks a content as safe.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Markup implements Countable
18
- {
19
- protected $content;
20
- protected $charset;
21
 
22
- public function __construct($content, $charset)
 
23
  {
24
- $this->content = (string) $content;
25
- $this->charset = $charset;
26
- }
27
-
28
- public function __toString()
29
- {
30
- return $this->content;
31
- }
32
-
33
- public function count()
34
- {
35
- return function_exists('mb_get_info') ? mb_strlen($this->content, $this->charset) : strlen($this->content);
36
  }
37
  }
38
-
39
- class_alias('Twig_Markup', 'Twig\Markup', false);
1
  <?php
2
 
3
+ use Twig\Markup;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Markup');
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Markup extends Markup
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node.php CHANGED
@@ -1,256 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Represents a node in the AST.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- class Twig_Node implements Twig_NodeInterface
19
- {
20
- protected $nodes;
21
- protected $attributes;
22
- protected $lineno;
23
- protected $tag;
24
 
25
- private $name;
26
-
27
- /**
28
- * Constructor.
29
- *
30
- * The nodes are automatically made available as properties ($this->node).
31
- * The attributes are automatically made available as array items ($this['name']).
32
- *
33
- * @param array $nodes An array of named nodes
34
- * @param array $attributes An array of attributes (should not be nodes)
35
- * @param int $lineno The line number
36
- * @param string $tag The tag name associated with the Node
37
- */
38
- public function __construct(array $nodes = [], array $attributes = [], $lineno = 0, $tag = null)
39
- {
40
- foreach ($nodes as $name => $node) {
41
- if (!$node instanceof Twig_NodeInterface) {
42
- @trigger_error(sprintf('Using "%s" for the value of node "%s" of "%s" is deprecated since version 1.25 and will be removed in 2.0.', is_object($node) ? get_class($node) : null === $node ? 'null' : gettype($node), $name, get_class($this)), E_USER_DEPRECATED);
43
- }
44
- }
45
- $this->nodes = $nodes;
46
- $this->attributes = $attributes;
47
- $this->lineno = $lineno;
48
- $this->tag = $tag;
49
- }
50
-
51
- public function __toString()
52
- {
53
- $attributes = [];
54
- foreach ($this->attributes as $name => $value) {
55
- $attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true)));
56
- }
57
-
58
- $repr = [get_class($this).'('.implode(', ', $attributes)];
59
-
60
- if (count($this->nodes)) {
61
- foreach ($this->nodes as $name => $node) {
62
- $len = strlen($name) + 4;
63
- $noderepr = [];
64
- foreach (explode("\n", (string) $node) as $line) {
65
- $noderepr[] = str_repeat(' ', $len).$line;
66
- }
67
-
68
- $repr[] = sprintf(' %s: %s', $name, ltrim(implode("\n", $noderepr)));
69
- }
70
-
71
- $repr[] = ')';
72
- } else {
73
- $repr[0] .= ')';
74
- }
75
-
76
- return implode("\n", $repr);
77
- }
78
-
79
- /**
80
- * @deprecated since 1.16.1 (to be removed in 2.0)
81
- */
82
- public function toXml($asDom = false)
83
- {
84
- @trigger_error(sprintf('%s is deprecated since version 1.16.1 and will be removed in 2.0.', __METHOD__), E_USER_DEPRECATED);
85
-
86
- $dom = new DOMDocument('1.0', 'UTF-8');
87
- $dom->formatOutput = true;
88
- $dom->appendChild($xml = $dom->createElement('twig'));
89
-
90
- $xml->appendChild($node = $dom->createElement('node'));
91
- $node->setAttribute('class', get_class($this));
92
-
93
- foreach ($this->attributes as $name => $value) {
94
- $node->appendChild($attribute = $dom->createElement('attribute'));
95
- $attribute->setAttribute('name', $name);
96
- $attribute->appendChild($dom->createTextNode($value));
97
- }
98
-
99
- foreach ($this->nodes as $name => $n) {
100
- if (null === $n) {
101
- continue;
102
- }
103
-
104
- $child = $n->toXml(true)->getElementsByTagName('node')->item(0);
105
- $child = $dom->importNode($child, true);
106
- $child->setAttribute('name', $name);
107
-
108
- $node->appendChild($child);
109
- }
110
-
111
- return $asDom ? $dom : $dom->saveXML();
112
- }
113
-
114
- public function compile(Twig_Compiler $compiler)
115
- {
116
- foreach ($this->nodes as $node) {
117
- $node->compile($compiler);
118
- }
119
- }
120
-
121
- public function getTemplateLine()
122
- {
123
- return $this->lineno;
124
- }
125
-
126
- /**
127
- * @deprecated since 1.27 (to be removed in 2.0)
128
- */
129
- public function getLine()
130
- {
131
- @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getTemplateLine() instead.', E_USER_DEPRECATED);
132
-
133
- return $this->lineno;
134
- }
135
-
136
- public function getNodeTag()
137
- {
138
- return $this->tag;
139
- }
140
-
141
- /**
142
- * @return bool
143
- */
144
- public function hasAttribute($name)
145
- {
146
- return array_key_exists($name, $this->attributes);
147
- }
148
-
149
- /**
150
- * @return mixed
151
- */
152
- public function getAttribute($name)
153
- {
154
- if (!array_key_exists($name, $this->attributes)) {
155
- throw new LogicException(sprintf('Attribute "%s" does not exist for Node "%s".', $name, get_class($this)));
156
- }
157
-
158
- return $this->attributes[$name];
159
- }
160
-
161
- /**
162
- * @param string $name
163
- * @param mixed $value
164
- */
165
- public function setAttribute($name, $value)
166
- {
167
- $this->attributes[$name] = $value;
168
- }
169
-
170
- public function removeAttribute($name)
171
- {
172
- unset($this->attributes[$name]);
173
- }
174
-
175
- /**
176
- * @return bool
177
- */
178
- public function hasNode($name)
179
- {
180
- return array_key_exists($name, $this->nodes);
181
- }
182
-
183
- /**
184
- * @return Twig_Node
185
- */
186
- public function getNode($name)
187
- {
188
- if (!array_key_exists($name, $this->nodes)) {
189
- throw new LogicException(sprintf('Node "%s" does not exist for Node "%s".', $name, get_class($this)));
190
- }
191
-
192
- return $this->nodes[$name];
193
- }
194
-
195
- public function setNode($name, $node = null)
196
- {
197
- if (!$node instanceof Twig_NodeInterface) {
198
- @trigger_error(sprintf('Using "%s" for the value of node "%s" of "%s" is deprecated since version 1.25 and will be removed in 2.0.', is_object($node) ? get_class($node) : null === $node ? 'null' : gettype($node), $name, get_class($this)), E_USER_DEPRECATED);
199
- }
200
-
201
- $this->nodes[$name] = $node;
202
- }
203
-
204
- public function removeNode($name)
205
- {
206
- unset($this->nodes[$name]);
207
- }
208
-
209
- public function count()
210
- {
211
- return count($this->nodes);
212
- }
213
-
214
- public function getIterator()
215
- {
216
- return new ArrayIterator($this->nodes);
217
- }
218
-
219
- public function setTemplateName($name)
220
- {
221
- $this->name = $name;
222
- foreach ($this->nodes as $node) {
223
- if (null !== $node) {
224
- $node->setTemplateName($name);
225
- }
226
- }
227
- }
228
-
229
- public function getTemplateName()
230
- {
231
- return $this->name;
232
- }
233
-
234
- /**
235
- * @deprecated since 1.27 (to be removed in 2.0)
236
- */
237
- public function setFilename($name)
238
- {
239
- @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use setTemplateName() instead.', E_USER_DEPRECATED);
240
-
241
- $this->setTemplateName($name);
242
- }
243
-
244
- /**
245
- * @deprecated since 1.27 (to be removed in 2.0)
246
- */
247
- public function getFilename()
248
  {
249
- @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getTemplateName() instead.', E_USER_DEPRECATED);
250
-
251
- return $this->name;
252
  }
253
  }
254
-
255
- class_alias('Twig_Node', 'Twig\Node\Node', false);
256
- class_exists('Twig_Compiler');
1
  <?php
2
 
3
+ use Twig\Node\Node;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Node');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node extends Node
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
10
  }
11
  }
 
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/AutoEscape.php CHANGED
@@ -1,36 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents an autoescape node.
14
- *
15
- * The value is the escaping strategy (can be html, js, ...)
16
- *
17
- * The true value is equivalent to html.
18
- *
19
- * If autoescaping is disabled, then the value is false.
20
- *
21
- * @author Fabien Potencier <fabien@symfony.com>
22
- */
23
- class Twig_Node_AutoEscape extends Twig_Node
24
- {
25
- public function __construct($value, Twig_NodeInterface $body, $lineno, $tag = 'autoescape')
26
- {
27
- parent::__construct(['body' => $body], ['value' => $value], $lineno, $tag);
28
- }
29
 
30
- public function compile(Twig_Compiler $compiler)
 
31
  {
32
- $compiler->subcompile($this->getNode('body'));
33
  }
34
  }
35
-
36
- class_alias('Twig_Node_AutoEscape', 'Twig\Node\AutoEscapeNode', false);
1
  <?php
2
 
3
+ use Twig\Node\AutoEscapeNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\AutoEscapeNode');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_AutoEscape extends AutoEscapeNode
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Block.php CHANGED
@@ -1,41 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Represents a block node.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- class Twig_Node_Block extends Twig_Node
19
- {
20
- public function __construct($name, Twig_NodeInterface $body, $lineno, $tag = null)
21
- {
22
- parent::__construct(['body' => $body], ['name' => $name], $lineno, $tag);
23
- }
24
 
25
- public function compile(Twig_Compiler $compiler)
 
26
  {
27
- $compiler
28
- ->addDebugInfo($this)
29
- ->write(sprintf("public function block_%s(\$context, array \$blocks = [])\n", $this->getAttribute('name')), "{\n")
30
- ->indent()
31
- ;
32
-
33
- $compiler
34
- ->subcompile($this->getNode('body'))
35
- ->outdent()
36
- ->write("}\n\n")
37
- ;
38
  }
39
  }
40
-
41
- class_alias('Twig_Node_Block', 'Twig\Node\BlockNode', false);
1
  <?php
2
 
3
+ use Twig\Node\BlockNode;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\BlockNode');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Block extends BlockNode
9
  {
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/BlockReference.php CHANGED
@@ -1,34 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Represents a block call node.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInterface
19
- {
20
- public function __construct($name, $lineno, $tag = null)
21
- {
22
- parent::__construct([], ['name' => $name], $lineno, $tag);
23
- }
24
 
25
- public function compile(Twig_Compiler $compiler)
 
26
  {
27
- $compiler
28
- ->addDebugInfo($this)
29
- ->write(sprintf("\$this->displayBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name')))
30
- ;
31
  }
32
  }
33
-
34
- class_alias('Twig_Node_BlockReference', 'Twig\Node\BlockReferenceNode', false);
1
  <?php
2
 
3
+ use Twig\Node\BlockReferenceNode;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\BlockReferenceNode');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_BlockReference extends BlockReferenceNode
9
  {
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Body.php CHANGED
@@ -1,21 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a body node.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Node_Body extends Twig_Node
18
- {
19
- }
20
 
21
- class_alias('Twig_Node_Body', 'Twig\Node\BodyNode', false);
 
 
 
 
1
  <?php
2
 
3
+ use Twig\Node\BodyNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\BodyNode');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Body extends BodyNode
9
+ {
10
+ }
11
+ }
src/lib/vendor/twig/twig/lib/Twig/Node/CheckSecurity.php CHANGED
@@ -1,80 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * @author Fabien Potencier <fabien@symfony.com>
14
- */
15
- class Twig_Node_CheckSecurity extends Twig_Node
16
- {
17
- protected $usedFilters;
18
- protected $usedTags;
19
- protected $usedFunctions;
20
 
21
- public function __construct(array $usedFilters, array $usedTags, array $usedFunctions)
 
22
  {
23
- $this->usedFilters = $usedFilters;
24
- $this->usedTags = $usedTags;
25
- $this->usedFunctions = $usedFunctions;
26
-
27
- parent::__construct();
28
- }
29
-
30
- public function compile(Twig_Compiler $compiler)
31
- {
32
- $tags = $filters = $functions = [];
33
- foreach (['tags', 'filters', 'functions'] as $type) {
34
- foreach ($this->{'used'.ucfirst($type)} as $name => $node) {
35
- if ($node instanceof Twig_Node) {
36
- ${$type}[$name] = $node->getTemplateLine();
37
- } else {
38
- ${$type}[$node] = null;
39
- }
40
- }
41
- }
42
-
43
- $compiler
44
- ->write('$tags = ')->repr(array_filter($tags))->raw(";\n")
45
- ->write('$filters = ')->repr(array_filter($filters))->raw(";\n")
46
- ->write('$functions = ')->repr(array_filter($functions))->raw(";\n\n")
47
- ->write("try {\n")
48
- ->indent()
49
- ->write("\$this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity(\n")
50
- ->indent()
51
- ->write(!$tags ? "[],\n" : "['".implode("', '", array_keys($tags))."'],\n")
52
- ->write(!$filters ? "[],\n" : "['".implode("', '", array_keys($filters))."'],\n")
53
- ->write(!$functions ? "[]\n" : "['".implode("', '", array_keys($functions))."']\n")
54
- ->outdent()
55
- ->write(");\n")
56
- ->outdent()
57
- ->write("} catch (Twig_Sandbox_SecurityError \$e) {\n")
58
- ->indent()
59
- ->write("\$e->setSourceContext(\$this->getSourceContext());\n\n")
60
- ->write("if (\$e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset(\$tags[\$e->getTagName()])) {\n")
61
- ->indent()
62
- ->write("\$e->setTemplateLine(\$tags[\$e->getTagName()]);\n")
63
- ->outdent()
64
- ->write("} elseif (\$e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset(\$filters[\$e->getFilterName()])) {\n")
65
- ->indent()
66
- ->write("\$e->setTemplateLine(\$filters[\$e->getFilterName()]);\n")
67
- ->outdent()
68
- ->write("} elseif (\$e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset(\$functions[\$e->getFunctionName()])) {\n")
69
- ->indent()
70
- ->write("\$e->setTemplateLine(\$functions[\$e->getFunctionName()]);\n")
71
- ->outdent()
72
- ->write("}\n\n")
73
- ->write("throw \$e;\n")
74
- ->outdent()
75
- ->write("}\n\n")
76
- ;
77
  }
78
  }
79
-
80
- class_alias('Twig_Node_CheckSecurity', 'Twig\Node\CheckSecurityNode', false);
1
  <?php
2
 
3
+ use Twig\Node\CheckSecurityNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\CheckSecurityNode');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_CheckSecurity extends CheckSecurityNode
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Deprecated.php CHANGED
@@ -1,49 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a deprecated node.
14
- *
15
- * @author Yonel Ceruto <yonelceruto@gmail.com>
16
- */
17
- class Twig_Node_Deprecated extends Twig_Node
18
- {
19
- public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
20
- {
21
- parent::__construct(['expr' => $expr], [], $lineno, $tag);
22
- }
23
 
24
- public function compile(Twig_Compiler $compiler)
 
25
  {
26
- $compiler->addDebugInfo($this);
27
-
28
- $expr = $this->getNode('expr');
29
-
30
- if ($expr instanceof Twig_Node_Expression_Constant) {
31
- $compiler->write('@trigger_error(')
32
- ->subcompile($expr);
33
- } else {
34
- $varName = $compiler->getVarName();
35
- $compiler->write(sprintf('$%s = ', $varName))
36
- ->subcompile($expr)
37
- ->raw(";\n")
38
- ->write(sprintf('@trigger_error($%s', $varName));
39
- }
40
-
41
- $compiler
42
- ->raw('.')
43
- ->string(sprintf(' ("%s" at line %d).', $this->getTemplateName(), $this->getTemplateLine()))
44
- ->raw(", E_USER_DEPRECATED);\n")
45
- ;
46
  }
47
  }
48
-
49
- class_alias('Twig_Node_Deprecated', 'Twig\Node\DeprecatedNode', false);
1
  <?php
2
 
3
+ use Twig\Node\DeprecatedNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\DeprecatedNode');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Deprecated extends DeprecatedNode
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Do.php CHANGED
@@ -1,35 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a do node.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Node_Do extends Twig_Node
18
- {
19
- public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
20
- {
21
- parent::__construct(['expr' => $expr], [], $lineno, $tag);
22
- }
23
 
24
- public function compile(Twig_Compiler $compiler)
 
25
  {
26
- $compiler
27
- ->addDebugInfo($this)
28
- ->write('')
29
- ->subcompile($this->getNode('expr'))
30
- ->raw(";\n")
31
- ;
32
  }
33
  }
34
-
35
- class_alias('Twig_Node_Do', 'Twig\Node\DoNode', false);
1
  <?php
2
 
3
+ use Twig\Node\DoNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\DoNode');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Do extends DoNode
9
  {
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Embed.php CHANGED
@@ -1,46 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents an embed node.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Node_Embed extends Twig_Node_Include
18
- {
19
- // we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module)
20
- public function __construct($name, $index, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
21
- {
22
- parent::__construct(new Twig_Node_Expression_Constant('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag);
23
-
24
- $this->setAttribute('name', $name);
25
- // to be removed in 2.0, used name instead
26
- $this->setAttribute('filename', $name);
27
- $this->setAttribute('index', $index);
28
- }
29
 
30
- protected function addGetTemplate(Twig_Compiler $compiler)
 
31
  {
32
- $compiler
33
- ->write('$this->loadTemplate(')
34
- ->string($this->getAttribute('name'))
35
- ->raw(', ')
36
- ->repr($this->getTemplateName())
37
- ->raw(', ')
38
- ->repr($this->getTemplateLine())
39
- ->raw(', ')
40
- ->string($this->getAttribute('index'))
41
- ->raw(')')
42
- ;
43
  }
44
  }
45
-
46
- class_alias('Twig_Node_Embed', 'Twig\Node\EmbedNode', false);
1
  <?php
2
 
3
+ use Twig\Node\EmbedNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\EmbedNode');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Embed extends EmbedNode
9
  {
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression.php CHANGED
@@ -1,22 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Abstract class for all nodes that represents an expression.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- abstract class Twig_Node_Expression extends Twig_Node
19
- {
20
- }
21
 
22
- class_alias('Twig_Node_Expression', 'Twig\Node\Expression\AbstractExpression', false);
 
 
 
 
1
  <?php
2
 
3
+ use Twig\Node\Expression\AbstractExpression;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\AbstractExpression');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression extends AbstractExpression
9
+ {
10
+ }
11
+ }
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Array.php CHANGED
@@ -1,83 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Array extends Twig_Node_Expression
12
- {
13
- protected $index;
14
 
15
- public function __construct(array $elements, $lineno)
16
- {
17
- parent::__construct($elements, [], $lineno);
18
-
19
- $this->index = -1;
20
- foreach ($this->getKeyValuePairs() as $pair) {
21
- if ($pair['key'] instanceof Twig_Node_Expression_Constant && ctype_digit((string) $pair['key']->getAttribute('value')) && $pair['key']->getAttribute('value') > $this->index) {
22
- $this->index = $pair['key']->getAttribute('value');
23
- }
24
- }
25
- }
26
-
27
- public function getKeyValuePairs()
28
- {
29
- $pairs = [];
30
-
31
- foreach (array_chunk($this->nodes, 2) as $pair) {
32
- $pairs[] = [
33
- 'key' => $pair[0],
34
- 'value' => $pair[1],
35
- ];
36
- }
37
-
38
- return $pairs;
39
- }
40
-
41
- public function hasElement(Twig_Node_Expression $key)
42
- {
43
- foreach ($this->getKeyValuePairs() as $pair) {
44
- // we compare the string representation of the keys
45
- // to avoid comparing the line numbers which are not relevant here.
46
- if ((string) $key === (string) $pair['key']) {
47
- return true;
48
- }
49
- }
50
-
51
- return false;
52
- }
53
 
54
- public function addElement(Twig_Node_Expression $value, Twig_Node_Expression $key = null)
 
55
  {
56
- if (null === $key) {
57
- $key = new Twig_Node_Expression_Constant(++$this->index, $value->getTemplateLine());
58
- }
59
-
60
- array_push($this->nodes, $key, $value);
61
- }
62
-
63
- public function compile(Twig_Compiler $compiler)
64
- {
65
- $compiler->raw('[');
66
- $first = true;
67
- foreach ($this->getKeyValuePairs() as $pair) {
68
- if (!$first) {
69
- $compiler->raw(', ');
70
- }
71
- $first = false;
72
-
73
- $compiler
74
- ->subcompile($pair['key'])
75
- ->raw(' => ')
76
- ->subcompile($pair['value'])
77
- ;
78
- }
79
- $compiler->raw(']');
80
  }
81
  }
82
-
83
- class_alias('Twig_Node_Expression_Array', 'Twig\Node\Expression\ArrayExpression', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\ArrayExpression;
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\ArrayExpression');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_Array extends ArrayExpression
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/AssignName.php CHANGED
@@ -1,25 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name
14
- {
15
- public function compile(Twig_Compiler $compiler)
 
16
  {
17
- $compiler
18
- ->raw('$context[')
19
- ->string($this->getAttribute('name'))
20
- ->raw(']')
21
- ;
22
  }
23
  }
24
-
25
- class_alias('Twig_Node_Expression_AssignName', 'Twig\Node\Expression\AssignNameExpression', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\AssignNameExpression;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\AssignNameExpression');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_AssignName extends AssignNameExpression
9
  {
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary.php CHANGED
@@ -1,37 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression
13
- {
14
- public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
15
- {
16
- parent::__construct(['left' => $left, 'right' => $right], [], $lineno);
17
- }
18
 
19
- public function compile(Twig_Compiler $compiler)
 
20
  {
21
- $compiler
22
- ->raw('(')
23
- ->subcompile($this->getNode('left'))
24
- ->raw(' ')
25
- ;
26
- $this->operator($compiler);
27
- $compiler
28
- ->raw(' ')
29
- ->subcompile($this->getNode('right'))
30
- ->raw(')')
31
- ;
32
  }
33
-
34
- abstract public function operator(Twig_Compiler $compiler);
35
  }
36
-
37
- class_alias('Twig_Node_Expression_Binary', 'Twig\Node\Expression\Binary\AbstractBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\AbstractBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\AbstractBinary');
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary extends AbstractBinary
9
  {
 
 
 
 
 
 
 
 
 
 
 
10
  }
 
 
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Add.php CHANGED
@@ -1,20 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Binary_Add extends Twig_Node_Expression_Binary
13
- {
14
- public function operator(Twig_Compiler $compiler)
15
  {
16
- return $compiler->raw('+');
17
  }
18
  }
19
-
20
- class_alias('Twig_Node_Expression_Binary_Add', 'Twig\Node\Expression\Binary\AddBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\AddBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\AddBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_Add extends AddBinary
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/And.php CHANGED
@@ -1,20 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Binary_And extends Twig_Node_Expression_Binary
13
- {
14
- public function operator(Twig_Compiler $compiler)
15
  {
16
- return $compiler->raw('&&');
17
  }
18
  }
19
-
20
- class_alias('Twig_Node_Expression_Binary_And', 'Twig\Node\Expression\Binary\AndBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\AndBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\AndBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_And extends AndBinary
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php CHANGED
@@ -1,20 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Binary_BitwiseAnd extends Twig_Node_Expression_Binary
13
- {
14
- public function operator(Twig_Compiler $compiler)
15
  {
16
- return $compiler->raw('&');
17
  }
18
  }
19
-
20
- class_alias('Twig_Node_Expression_Binary_BitwiseAnd', 'Twig\Node\Expression\Binary\BitwiseAndBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\BitwiseAndBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\BitwiseAndBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_BitwiseAnd extends BitwiseAndBinary
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php CHANGED
@@ -1,20 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Binary_BitwiseOr extends Twig_Node_Expression_Binary
13
- {
14
- public function operator(Twig_Compiler $compiler)
15
  {
16
- return $compiler->raw('|');
17
  }
18
  }
19
-
20
- class_alias('Twig_Node_Expression_Binary_BitwiseOr', 'Twig\Node\Expression\Binary\BitwiseOrBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\BitwiseOrBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\BitwiseOrBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_BitwiseOr extends BitwiseOrBinary
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php CHANGED
@@ -1,20 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Binary_BitwiseXor extends Twig_Node_Expression_Binary
13
- {
14
- public function operator(Twig_Compiler $compiler)
15
  {
16
- return $compiler->raw('^');
17
  }
18
  }
19
-
20
- class_alias('Twig_Node_Expression_Binary_BitwiseXor', 'Twig\Node\Expression\Binary\BitwiseXorBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\BitwiseXorBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\BitwiseXorBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_BitwiseXor extends BitwiseXorBinary
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Concat.php CHANGED
@@ -1,20 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Binary_Concat extends Twig_Node_Expression_Binary
13
- {
14
- public function operator(Twig_Compiler $compiler)
15
  {
16
- return $compiler->raw('.');
17
  }
18
  }
19
-
20
- class_alias('Twig_Node_Expression_Binary_Concat', 'Twig\Node\Expression\Binary\ConcatBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\ConcatBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\ConcatBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_Concat extends ConcatBinary
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Div.php CHANGED
@@ -1,20 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Binary_Div extends Twig_Node_Expression_Binary
13
- {
14
- public function operator(Twig_Compiler $compiler)
15
  {
16
- return $compiler->raw('/');
17
  }
18
  }
19
-
20
- class_alias('Twig_Node_Expression_Binary_Div', 'Twig\Node\Expression\Binary\DivBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\DivBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\DivBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_Div extends DivBinary
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php CHANGED
@@ -1,32 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Binary_EndsWith extends Twig_Node_Expression_Binary
12
- {
13
- public function compile(Twig_Compiler $compiler)
14
- {
15
- $left = $compiler->getVarName();
16
- $right = $compiler->getVarName();
17
- $compiler
18
- ->raw(sprintf('(is_string($%s = ', $left))
19
- ->subcompile($this->getNode('left'))
20
- ->raw(sprintf(') && is_string($%s = ', $right))
21
- ->subcompile($this->getNode('right'))
22
- ->raw(sprintf(') && (\'\' === $%2$s || $%2$s === substr($%1$s, -strlen($%2$s))))', $left, $right))
23
- ;
24
- }
25
 
26
- public function operator(Twig_Compiler $compiler)
 
 
 
27
  {
28
- return $compiler->raw('');
29
  }
30
  }
31
-
32
- class_alias('Twig_Node_Expression_Binary_EndsWith', 'Twig\Node\Expression\Binary\EndsWithBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\EndsWithBinary;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Binary\EndsWithBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_EndsWith extends EndsWithBinary
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Equal.php CHANGED
@@ -1,19 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Binary_Equal extends Twig_Node_Expression_Binary
12
- {
13
- public function operator(Twig_Compiler $compiler)
14
  {
15
- return $compiler->raw('==');
16
  }
17
  }
18
-
19
- class_alias('Twig_Node_Expression_Binary_Equal', 'Twig\Node\Expression\Binary\EqualBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\EqualBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\EqualBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_Equal extends EqualBinary
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php CHANGED
@@ -1,26 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Binary_FloorDiv extends Twig_Node_Expression_Binary
12
- {
13
- public function compile(Twig_Compiler $compiler)
14
- {
15
- $compiler->raw('(int) floor(');
16
- parent::compile($compiler);
17
- $compiler->raw(')');
18
- }
19
 
20
- public function operator(Twig_Compiler $compiler)
 
 
 
21
  {
22
- return $compiler->raw('/');
23
  }
24
  }
25
-
26
- class_alias('Twig_Node_Expression_Binary_FloorDiv', 'Twig\Node\Expression\Binary\FloorDivBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\FloorDivBinary;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Binary\FloorDivBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_FloorDiv extends FloorDivBinary
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Greater.php CHANGED
@@ -1,19 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Binary_Greater extends Twig_Node_Expression_Binary
12
- {
13
- public function operator(Twig_Compiler $compiler)
14
  {
15
- return $compiler->raw('>');
16
  }
17
  }
18
-
19
- class_alias('Twig_Node_Expression_Binary_Greater', 'Twig\Node\Expression\Binary\GreaterBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\GreaterBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\GreaterBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_Greater extends GreaterBinary
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php CHANGED
@@ -1,19 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Binary_GreaterEqual extends Twig_Node_Expression_Binary
12
- {
13
- public function operator(Twig_Compiler $compiler)
14
  {
15
- return $compiler->raw('>=');
16
  }
17
  }
18
-
19
- class_alias('Twig_Node_Expression_Binary_GreaterEqual', 'Twig\Node\Expression\Binary\GreaterEqualBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\GreaterEqualBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\GreaterEqualBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_GreaterEqual extends GreaterEqualBinary
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/In.php CHANGED
@@ -1,30 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary
12
- {
13
- public function compile(Twig_Compiler $compiler)
14
- {
15
- $compiler
16
- ->raw('twig_in_filter(')
17
- ->subcompile($this->getNode('left'))
18
- ->raw(', ')
19
- ->subcompile($this->getNode('right'))
20
- ->raw(')')
21
- ;
22
- }
23
 
24
- public function operator(Twig_Compiler $compiler)
 
 
 
25
  {
26
- return $compiler->raw('in');
27
  }
28
  }
29
-
30
- class_alias('Twig_Node_Expression_Binary_In', 'Twig\Node\Expression\Binary\InBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\InBinary;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Binary\InBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_In extends InBinary
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Less.php CHANGED
@@ -1,19 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Binary_Less extends Twig_Node_Expression_Binary
12
- {
13
- public function operator(Twig_Compiler $compiler)
14
  {
15
- return $compiler->raw('<');
16
  }
17
  }
18
-
19
- class_alias('Twig_Node_Expression_Binary_Less', 'Twig\Node\Expression\Binary\LessBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\LessBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\LessBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_Less extends LessBinary
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/LessEqual.php CHANGED
@@ -1,19 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Binary_LessEqual extends Twig_Node_Expression_Binary
12
- {
13
- public function operator(Twig_Compiler $compiler)
14
  {
15
- return $compiler->raw('<=');
16
  }
17
  }
18
-
19
- class_alias('Twig_Node_Expression_Binary_LessEqual', 'Twig\Node\Expression\Binary\LessEqualBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\LessEqualBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\LessEqualBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_LessEqual extends LessEqualBinary
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php CHANGED
@@ -1,30 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Binary_Matches extends Twig_Node_Expression_Binary
12
- {
13
- public function compile(Twig_Compiler $compiler)
14
- {
15
- $compiler
16
- ->raw('preg_match(')
17
- ->subcompile($this->getNode('right'))
18
- ->raw(', ')
19
- ->subcompile($this->getNode('left'))
20
- ->raw(')')
21
- ;
22
- }
23
 
24
- public function operator(Twig_Compiler $compiler)
 
 
 
25
  {
26
- return $compiler->raw('');
27
  }
28
  }
29
-
30
- class_alias('Twig_Node_Expression_Binary_Matches', 'Twig\Node\Expression\Binary\MatchesBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\MatchesBinary;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Binary\MatchesBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_Matches extends MatchesBinary
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mod.php CHANGED
@@ -1,20 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Binary_Mod extends Twig_Node_Expression_Binary
13
- {
14
- public function operator(Twig_Compiler $compiler)
15
  {
16
- return $compiler->raw('%');
17
  }
18
  }
19
-
20
- class_alias('Twig_Node_Expression_Binary_Mod', 'Twig\Node\Expression\Binary\ModBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\ModBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\ModBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_Mod extends ModBinary
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mul.php CHANGED
@@ -1,20 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Binary_Mul extends Twig_Node_Expression_Binary
13
- {
14
- public function operator(Twig_Compiler $compiler)
15
  {
16
- return $compiler->raw('*');
17
  }
18
  }
19
-
20
- class_alias('Twig_Node_Expression_Binary_Mul', 'Twig\Node\Expression\Binary\MulBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\MulBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\MulBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_Mul extends MulBinary
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotEqual.php CHANGED
@@ -1,19 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Binary_NotEqual extends Twig_Node_Expression_Binary
12
- {
13
- public function operator(Twig_Compiler $compiler)
14
  {
15
- return $compiler->raw('!=');
16
  }
17
  }
18
-
19
- class_alias('Twig_Node_Expression_Binary_NotEqual', 'Twig\Node\Expression\Binary\NotEqualBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\NotEqualBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\NotEqualBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_NotEqual extends NotEqualBinary
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php CHANGED
@@ -1,30 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary
12
- {
13
- public function compile(Twig_Compiler $compiler)
14
- {
15
- $compiler
16
- ->raw('!twig_in_filter(')
17
- ->subcompile($this->getNode('left'))
18
- ->raw(', ')
19
- ->subcompile($this->getNode('right'))
20
- ->raw(')')
21
- ;
22
- }
23
 
24
- public function operator(Twig_Compiler $compiler)
 
 
 
25
  {
26
- return $compiler->raw('not in');
27
  }
28
  }
29
-
30
- class_alias('Twig_Node_Expression_Binary_NotIn', 'Twig\Node\Expression\Binary\NotInBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\NotInBinary;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Binary\NotInBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_NotIn extends NotInBinary
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Or.php CHANGED
@@ -1,20 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Binary_Or extends Twig_Node_Expression_Binary
13
- {
14
- public function operator(Twig_Compiler $compiler)
15
  {
16
- return $compiler->raw('||');
17
  }
18
  }
19
-
20
- class_alias('Twig_Node_Expression_Binary_Or', 'Twig\Node\Expression\Binary\OrBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\OrBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\OrBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_Or extends OrBinary
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Power.php CHANGED
@@ -1,34 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary
12
- {
13
- public function compile(Twig_Compiler $compiler)
14
- {
15
- if (PHP_VERSION_ID >= 50600) {
16
- return parent::compile($compiler);
17
- }
18
 
19
- $compiler
20
- ->raw('pow(')
21
- ->subcompile($this->getNode('left'))
22
- ->raw(', ')
23
- ->subcompile($this->getNode('right'))
24
- ->raw(')')
25
- ;
26
- }
27
 
28
- public function operator(Twig_Compiler $compiler)
 
29
  {
30
- return $compiler->raw('**');
31
  }
32
  }
33
-
34
- class_alias('Twig_Node_Expression_Binary_Power', 'Twig\Node\Expression\Binary\PowerBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\PowerBinary;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Binary\PowerBinary');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_Power extends PowerBinary
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Range.php CHANGED
@@ -1,30 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary
12
- {
13
- public function compile(Twig_Compiler $compiler)
14
- {
15
- $compiler
16
- ->raw('range(')
17
- ->subcompile($this->getNode('left'))
18
- ->raw(', ')
19
- ->subcompile($this->getNode('right'))
20
- ->raw(')')
21
- ;
22
- }
23
 
24
- public function operator(Twig_Compiler $compiler)
 
 
 
25
  {
26
- return $compiler->raw('..');
27
  }
28
  }
29
-
30
- class_alias('Twig_Node_Expression_Binary_Range', 'Twig\Node\Expression\Binary\RangeBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\RangeBinary;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Binary\RangeBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_Range extends RangeBinary
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php CHANGED
@@ -1,32 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Binary_StartsWith extends Twig_Node_Expression_Binary
12
- {
13
- public function compile(Twig_Compiler $compiler)
14
- {
15
- $left = $compiler->getVarName();
16
- $right = $compiler->getVarName();
17
- $compiler
18
- ->raw(sprintf('(is_string($%s = ', $left))
19
- ->subcompile($this->getNode('left'))
20
- ->raw(sprintf(') && is_string($%s = ', $right))
21
- ->subcompile($this->getNode('right'))
22
- ->raw(sprintf(') && (\'\' === $%2$s || 0 === strpos($%1$s, $%2$s)))', $left, $right))
23
- ;
24
- }
25
 
26
- public function operator(Twig_Compiler $compiler)
 
 
 
27
  {
28
- return $compiler->raw('');
29
  }
30
  }
31
-
32
- class_alias('Twig_Node_Expression_Binary_StartsWith', 'Twig\Node\Expression\Binary\StartsWithBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\StartsWithBinary;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Binary\StartsWithBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_StartsWith extends StartsWithBinary
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Sub.php CHANGED
@@ -1,20 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Binary_Sub extends Twig_Node_Expression_Binary
13
- {
14
- public function operator(Twig_Compiler $compiler)
15
  {
16
- return $compiler->raw('-');
17
  }
18
  }
19
-
20
- class_alias('Twig_Node_Expression_Binary_Sub', 'Twig\Node\Expression\Binary\SubBinary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Binary\SubBinary;
4
+
5
+ class_exists('Twig\Node\Expression\Binary\SubBinary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Binary_Sub extends SubBinary
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.php CHANGED
@@ -1,93 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Represents a block call node.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
19
- {
20
- /**
21
- * @param Twig_Node|null $template
22
- */
23
- public function __construct(Twig_NodeInterface $name, $template = null, $lineno, $tag = null)
24
- {
25
- if (is_bool($template)) {
26
- @trigger_error(sprintf('The %s method "$asString" argument is deprecated since version 1.28 and will be removed in 2.0.', __METHOD__), E_USER_DEPRECATED);
27
-
28
- $template = null;
29
- }
30
-
31
- $nodes = ['name' => $name];
32
- if (null !== $template) {
33
- $nodes['template'] = $template;
34
- }
35
-
36
- parent::__construct($nodes, ['is_defined_test' => false, 'output' => false], $lineno, $tag);
37
- }
38
 
39
- public function compile(Twig_Compiler $compiler)
 
40
  {
41
- if ($this->getAttribute('is_defined_test')) {
42
- $this->compileTemplateCall($compiler, 'hasBlock');
43
- } else {
44
- if ($this->getAttribute('output')) {
45
- $compiler->addDebugInfo($this);
46
-
47
- $this
48
- ->compileTemplateCall($compiler, 'displayBlock')
49
- ->raw(";\n");
50
- } else {
51
- $this->compileTemplateCall($compiler, 'renderBlock');
52
- }
53
- }
54
- }
55
-
56
- private function compileTemplateCall(Twig_Compiler $compiler, $method)
57
- {
58
- if (!$this->hasNode('template')) {
59
- $compiler->write('$this');
60
- } else {
61
- $compiler
62
- ->write('$this->loadTemplate(')
63
- ->subcompile($this->getNode('template'))
64
- ->raw(', ')
65
- ->repr($this->getTemplateName())
66
- ->raw(', ')
67
- ->repr($this->getTemplateLine())
68
- ->raw(')')
69
- ;
70
- }
71
-
72
- $compiler->raw(sprintf('->%s', $method));
73
- $this->compileBlockArguments($compiler);
74
-
75
- return $compiler;
76
- }
77
-
78
- private function compileBlockArguments(Twig_Compiler $compiler)
79
- {
80
- $compiler
81
- ->raw('(')
82
- ->subcompile($this->getNode('name'))
83
- ->raw(', $context');
84
-
85
- if (!$this->hasNode('template')) {
86
- $compiler->raw(', $blocks');
87
- }
88
-
89
- return $compiler->raw(')');
90
  }
91
  }
92
-
93
- class_alias('Twig_Node_Expression_BlockReference', 'Twig\Node\Expression\BlockReferenceExpression', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\BlockReferenceExpression;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\BlockReferenceExpression');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_BlockReference extends BlockReferenceExpression
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Call.php CHANGED
@@ -1,293 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
12
- {
13
- private $reflector;
14
 
15
- protected function compileCallable(Twig_Compiler $compiler)
16
- {
17
- $closingParenthesis = false;
18
- $isArray = false;
19
- if ($this->hasAttribute('callable') && $callable = $this->getAttribute('callable')) {
20
- if (is_string($callable) && false === strpos($callable, '::')) {
21
- $compiler->raw($callable);
22
- } else {
23
- list($r, $callable) = $this->reflectCallable($callable);
24
- if ($r instanceof ReflectionMethod && is_string($callable[0])) {
25
- if ($r->isStatic()) {
26
- $compiler->raw(sprintf('%s::%s', $callable[0], $callable[1]));
27
- } else {
28
- $compiler->raw(sprintf('$this->env->getRuntime(\'%s\')->%s', $callable[0], $callable[1]));
29
- }
30
- } elseif ($r instanceof ReflectionMethod && $callable[0] instanceof Twig_ExtensionInterface) {
31
- $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', get_class($callable[0]), $callable[1]));
32
- } else {
33
- $type = ucfirst($this->getAttribute('type'));
34
- $compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), ', $type, $this->getAttribute('name')));
35
- $closingParenthesis = true;
36
- $isArray = true;
37
- }
38
- }
39
- } else {
40
- $compiler->raw($this->getAttribute('thing')->compile());
41
- }
42
-
43
- $this->compileArguments($compiler, $isArray);
44
-
45
- if ($closingParenthesis) {
46
- $compiler->raw(')');
47
- }
48
- }
49
 
50
- protected function compileArguments(Twig_Compiler $compiler, $isArray = false)
 
51
  {
52
- $compiler->raw($isArray ? '[' : '(');
53
-
54
- $first = true;
55
-
56
- if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
57
- $compiler->raw('$this->env');
58
- $first = false;
59
- }
60
-
61
- if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
62
- if (!$first) {
63
- $compiler->raw(', ');
64
- }
65
- $compiler->raw('$context');
66
- $first = false;
67
- }
68
-
69
- if ($this->hasAttribute('arguments')) {
70
- foreach ($this->getAttribute('arguments') as $argument) {
71
- if (!$first) {
72
- $compiler->raw(', ');
73
- }
74
- $compiler->string($argument);
75
- $first = false;
76
- }
77
- }
78
-
79
- if ($this->hasNode('node')) {
80
- if (!$first) {
81
- $compiler->raw(', ');
82
- }
83
- $compiler->subcompile($this->getNode('node'));
84
- $first = false;
85
- }
86
-
87
- if ($this->hasNode('arguments')) {
88
- $callable = $this->hasAttribute('callable') ? $this->getAttribute('callable') : null;
89
-
90
- $arguments = $this->getArguments($callable, $this->getNode('arguments'));
91
-
92
- foreach ($arguments as $node) {
93
- if (!$first) {
94
- $compiler->raw(', ');
95
- }
96
- $compiler->subcompile($node);
97
- $first = false;
98
- }
99
- }
100
-
101
- $compiler->raw($isArray ? ']' : ')');
102
- }
103
-
104
- protected function getArguments($callable, $arguments)
105
- {
106
- $callType = $this->getAttribute('type');
107
- $callName = $this->getAttribute('name');
108
-
109
- $parameters = [];
110
- $named = false;
111
- foreach ($arguments as $name => $node) {
112
- if (!is_int($name)) {
113
- $named = true;
114
- $name = $this->normalizeName($name);
115
- } elseif ($named) {
116
- throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName), $this->getTemplateLine());
117
- }
118
-
119
- $parameters[$name] = $node;
120
- }
121
-
122
- $isVariadic = $this->hasAttribute('is_variadic') && $this->getAttribute('is_variadic');
123
- if (!$named && !$isVariadic) {
124
- return $parameters;
125
- }
126
-
127
- if (!$callable) {
128
- if ($named) {
129
- $message = sprintf('Named arguments are not supported for %s "%s".', $callType, $callName);
130
- } else {
131
- $message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName);
132
- }
133
-
134
- throw new LogicException($message);
135
- }
136
-
137
- $callableParameters = $this->getCallableParameters($callable, $isVariadic);
138
- $arguments = [];
139
- $names = [];
140
- $missingArguments = [];
141
- $optionalArguments = [];
142
- $pos = 0;
143
- foreach ($callableParameters as $callableParameter) {
144
- $names[] = $name = $this->normalizeName($callableParameter->name);
145
-
146
- if (array_key_exists($name, $parameters)) {
147
- if (array_key_exists($pos, $parameters)) {
148
- throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName), $this->getTemplateLine());
149
- }
150
-
151
- if (count($missingArguments)) {
152
- throw new Twig_Error_Syntax(sprintf(
153
- 'Argument "%s" could not be assigned for %s "%s(%s)" because it is mapped to an internal PHP function which cannot determine default value for optional argument%s "%s".',
154
- $name, $callType, $callName, implode(', ', $names), count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments)
155
- ), $this->getTemplateLine());
156
- }
157
-
158
- $arguments = array_merge($arguments, $optionalArguments);
159
- $arguments[] = $parameters[$name];
160
- unset($parameters[$name]);
161
- $optionalArguments = [];
162
- } elseif (array_key_exists($pos, $parameters)) {
163
- $arguments = array_merge($arguments, $optionalArguments);
164
- $arguments[] = $parameters[$pos];
165
- unset($parameters[$pos]);
166
- $optionalArguments = [];
167
- ++$pos;
168
- } elseif ($callableParameter->isDefaultValueAvailable()) {
169
- $optionalArguments[] = new Twig_Node_Expression_Constant($callableParameter->getDefaultValue(), -1);
170
- } elseif ($callableParameter->isOptional()) {
171
- if (empty($parameters)) {
172
- break;
173
- } else {
174
- $missingArguments[] = $name;
175
- }
176
- } else {
177
- throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName), $this->getTemplateLine());
178
- }
179
- }
180
-
181
- if ($isVariadic) {
182
- $arbitraryArguments = new Twig_Node_Expression_Array([], -1);
183
- foreach ($parameters as $key => $value) {
184
- if (is_int($key)) {
185
- $arbitraryArguments->addElement($value);
186
- } else {
187
- $arbitraryArguments->addElement($value, new Twig_Node_Expression_Constant($key, -1));
188
- }
189
- unset($parameters[$key]);
190
- }
191
-
192
- if ($arbitraryArguments->count()) {
193
- $arguments = array_merge($arguments, $optionalArguments);
194
- $arguments[] = $arbitraryArguments;
195
- }
196
- }
197
-
198
- if (!empty($parameters)) {
199
- $unknownParameter = null;
200
- foreach ($parameters as $parameter) {
201
- if ($parameter instanceof Twig_Node) {
202
- $unknownParameter = $parameter;
203
- break;
204
- }
205
- }
206
-
207
- throw new Twig_Error_Syntax(sprintf(
208
- 'Unknown argument%s "%s" for %s "%s(%s)".',
209
- count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names)
210
- ), $unknownParameter ? $unknownParameter->getTemplateLine() : $this->getTemplateLine());
211
- }
212
-
213
- return $arguments;
214
- }
215
-
216
- protected function normalizeName($name)
217
- {
218
- return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], ['\\1_\\2', '\\1_\\2'], $name));
219
- }
220
-
221
- private function getCallableParameters($callable, $isVariadic)
222
- {
223
- list($r) = $this->reflectCallable($callable);
224
- if (null === $r) {
225
- return [];
226
- }
227
-
228
- $parameters = $r->getParameters();
229
- if ($this->hasNode('node')) {
230
- array_shift($parameters);
231
- }
232
- if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
233
- array_shift($parameters);
234
- }
235
- if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
236
- array_shift($parameters);
237
- }
238
- if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) {
239
- foreach ($this->getAttribute('arguments') as $argument) {
240
- array_shift($parameters);
241
- }
242
- }
243
- if ($isVariadic) {
244
- $argument = end($parameters);
245
- if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && [] === $argument->getDefaultValue()) {
246
- array_pop($parameters);
247
- } else {
248
- $callableName = $r->name;
249
- if ($r instanceof ReflectionMethod) {
250
- $callableName = $r->getDeclaringClass()->name.'::'.$callableName;
251
- }
252
-
253
- throw new LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = []".', $callableName, $this->getAttribute('type'), $this->getAttribute('name')));
254
- }
255
- }
256
-
257
- return $parameters;
258
- }
259
-
260
- private function reflectCallable($callable)
261
- {
262
- if (null !== $this->reflector) {
263
- return $this->reflector;
264
- }
265
-
266
- if (is_array($callable)) {
267
- if (!method_exists($callable[0], $callable[1])) {
268
- // __call()
269
- return [null, []];
270
- }
271
- $r = new ReflectionMethod($callable[0], $callable[1]);
272
- } elseif (is_object($callable) && !$callable instanceof Closure) {
273
- $r = new ReflectionObject($callable);
274
- $r = $r->getMethod('__invoke');
275
- $callable = [$callable, '__invoke'];
276
- } elseif (is_string($callable) && false !== $pos = strpos($callable, '::')) {
277
- $class = substr($callable, 0, $pos);
278
- $method = substr($callable, $pos + 2);
279
- if (!method_exists($class, $method)) {
280
- // __staticCall()
281
- return [null, []];
282
- }
283
- $r = new ReflectionMethod($callable);
284
- $callable = [$class, $method];
285
- } else {
286
- $r = new ReflectionFunction($callable);
287
- }
288
-
289
- return $this->reflector = [$r, $callable];
290
  }
291
  }
292
-
293
- class_alias('Twig_Node_Expression_Call', 'Twig\Node\Expression\CallExpression', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\CallExpression;
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\CallExpression');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_Call extends CallExpression
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Conditional.php CHANGED
@@ -1,33 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Conditional extends Twig_Node_Expression
13
- {
14
- public function __construct(Twig_Node_Expression $expr1, Twig_Node_Expression $expr2, Twig_Node_Expression $expr3, $lineno)
15
- {
16
- parent::__construct(['expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3], [], $lineno);
17
- }
18
 
19
- public function compile(Twig_Compiler $compiler)
 
 
 
20
  {
21
- $compiler
22
- ->raw('((')
23
- ->subcompile($this->getNode('expr1'))
24
- ->raw(') ? (')
25
- ->subcompile($this->getNode('expr2'))
26
- ->raw(') : (')
27
- ->subcompile($this->getNode('expr3'))
28
- ->raw('))')
29
- ;
30
  }
31
  }
32
-
33
- class_alias('Twig_Node_Expression_Conditional', 'Twig\Node\Expression\ConditionalExpression', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\ConditionalExpression;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\ConditionalExpression');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Conditional extends ConditionalExpression
9
  {
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Constant.php CHANGED
@@ -1,25 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Constant extends Twig_Node_Expression
13
- {
14
- public function __construct($value, $lineno)
15
- {
16
- parent::__construct([], ['value' => $value], $lineno);
17
- }
18
 
19
- public function compile(Twig_Compiler $compiler)
 
 
 
20
  {
21
- $compiler->repr($this->getAttribute('value'));
22
  }
23
  }
24
-
25
- class_alias('Twig_Node_Expression_Constant', 'Twig\Node\Expression\ConstantExpression', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\ConstantExpression;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\ConstantExpression');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Constant extends ConstantExpression
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php CHANGED
@@ -9,6 +9,9 @@
9
  * file that was distributed with this source code.
10
  */
11
 
 
 
 
12
  @trigger_error('The Twig_Node_Expression_ExtensionReference class is deprecated since version 1.23 and will be removed in 2.0.', E_USER_DEPRECATED);
13
 
14
  /**
@@ -18,14 +21,14 @@
18
  *
19
  * @deprecated since 1.23 and will be removed in 2.0.
20
  */
21
- class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression
22
  {
23
  public function __construct($name, $lineno, $tag = null)
24
  {
25
  parent::__construct([], ['name' => $name], $lineno, $tag);
26
  }
27
 
28
- public function compile(Twig_Compiler $compiler)
29
  {
30
  $compiler->raw(sprintf("\$this->env->getExtension('%s')", $this->getAttribute('name')));
31
  }
9
  * file that was distributed with this source code.
10
  */
11
 
12
+ use Twig\Compiler;
13
+ use Twig\Node\Expression\AbstractExpression;
14
+
15
  @trigger_error('The Twig_Node_Expression_ExtensionReference class is deprecated since version 1.23 and will be removed in 2.0.', E_USER_DEPRECATED);
16
 
17
  /**
21
  *
22
  * @deprecated since 1.23 and will be removed in 2.0.
23
  */
24
+ class Twig_Node_Expression_ExtensionReference extends AbstractExpression
25
  {
26
  public function __construct($name, $lineno, $tag = null)
27
  {
28
  parent::__construct([], ['name' => $name], $lineno, $tag);
29
  }
30
 
31
+ public function compile(Compiler $compiler)
32
  {
33
  $compiler->raw(sprintf("\$this->env->getExtension('%s')", $this->getAttribute('name')));
34
  }
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Filter.php CHANGED
@@ -1,41 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call
13
- {
14
- public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
15
- {
16
- parent::__construct(['node' => $node, 'filter' => $filterName, 'arguments' => $arguments], [], $lineno, $tag);
17
- }
18
-
19
- public function compile(Twig_Compiler $compiler)
20
- {
21
- $name = $this->getNode('filter')->getAttribute('value');
22
- $filter = $compiler->getEnvironment()->getFilter($name);
23
 
24
- $this->setAttribute('name', $name);
25
- $this->setAttribute('type', 'filter');
26
- $this->setAttribute('thing', $filter);
27
- $this->setAttribute('needs_environment', $filter->needsEnvironment());
28
- $this->setAttribute('needs_context', $filter->needsContext());
29
- $this->setAttribute('arguments', $filter->getArguments());
30
- if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof Twig_SimpleFilter) {
31
- $this->setAttribute('callable', $filter->getCallable());
32
- }
33
- if ($filter instanceof Twig_SimpleFilter) {
34
- $this->setAttribute('is_variadic', $filter->isVariadic());
35
- }
36
 
37
- $this->compileCallable($compiler);
 
 
38
  }
39
  }
40
-
41
- class_alias('Twig_Node_Expression_Filter', 'Twig\Node\Expression\FilterExpression', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\FilterExpression;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\FilterExpression');
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_Filter extends FilterExpression
9
+ {
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Filter/Default.php CHANGED
@@ -1,45 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Returns the value or the default value when it is undefined or empty.
14
- *
15
- * <pre>
16
- * {{ var.foo|default('foo item on var is not defined') }}
17
- * </pre>
18
- *
19
- * @author Fabien Potencier <fabien@symfony.com>
20
- */
21
- class Twig_Node_Expression_Filter_Default extends Twig_Node_Expression_Filter
22
- {
23
- public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
24
- {
25
- $default = new Twig_Node_Expression_Filter($node, new Twig_Node_Expression_Constant('default', $node->getTemplateLine()), $arguments, $node->getTemplateLine());
26
-
27
- if ('default' === $filterName->getAttribute('value') && ($node instanceof Twig_Node_Expression_Name || $node instanceof Twig_Node_Expression_GetAttr)) {
28
- $test = new Twig_Node_Expression_Test_Defined(clone $node, 'defined', new Twig_Node(), $node->getTemplateLine());
29
- $false = count($arguments) ? $arguments->getNode(0) : new Twig_Node_Expression_Constant('', $node->getTemplateLine());
30
-
31
- $node = new Twig_Node_Expression_Conditional($test, $default, $false, $node->getTemplateLine());
32
- } else {
33
- $node = $default;
34
- }
35
 
36
- parent::__construct($node, $filterName, $arguments, $lineno, $tag);
37
- }
38
-
39
- public function compile(Twig_Compiler $compiler)
40
  {
41
- $compiler->subcompile($this->getNode('node'));
42
  }
43
  }
44
-
45
- class_alias('Twig_Node_Expression_Filter_Default', 'Twig\Node\Expression\Filter\DefaultFilter', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Filter\DefaultFilter;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Filter\DefaultFilter');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_Filter_Default extends DefaultFilter
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Function.php CHANGED
@@ -1,45 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
12
- {
13
- public function __construct($name, Twig_NodeInterface $arguments, $lineno)
14
- {
15
- parent::__construct(['arguments' => $arguments], ['name' => $name, 'is_defined_test' => false], $lineno);
16
- }
17
-
18
- public function compile(Twig_Compiler $compiler)
19
- {
20
- $name = $this->getAttribute('name');
21
- $function = $compiler->getEnvironment()->getFunction($name);
22
 
23
- $this->setAttribute('name', $name);
24
- $this->setAttribute('type', 'function');
25
- $this->setAttribute('thing', $function);
26
- $this->setAttribute('needs_environment', $function->needsEnvironment());
27
- $this->setAttribute('needs_context', $function->needsContext());
28
- $this->setAttribute('arguments', $function->getArguments());
29
- if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) {
30
- $callable = $function->getCallable();
31
- if ('constant' === $name && $this->getAttribute('is_defined_test')) {
32
- $callable = 'twig_constant_is_defined';
33
- }
34
 
35
- $this->setAttribute('callable', $callable);
36
- }
37
- if ($function instanceof Twig_SimpleFunction) {
38
- $this->setAttribute('is_variadic', $function->isVariadic());
39
- }
40
-
41
- $this->compileCallable($compiler);
42
  }
43
  }
44
-
45
- class_alias('Twig_Node_Expression_Function', 'Twig\Node\Expression\FunctionExpression', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\FunctionExpression;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\FunctionExpression');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_Function extends FunctionExpression
9
+ {
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php CHANGED
@@ -1,74 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
13
- {
14
- public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression $arguments = null, $type, $lineno)
15
- {
16
- $nodes = ['node' => $node, 'attribute' => $attribute];
17
- if (null !== $arguments) {
18
- $nodes['arguments'] = $arguments;
19
- }
20
 
21
- parent::__construct($nodes, ['type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false], $lineno);
22
- }
23
 
24
- public function compile(Twig_Compiler $compiler)
 
25
  {
26
- if ($this->getAttribute('disable_c_ext')) {
27
- @trigger_error(sprintf('Using the "disable_c_ext" attribute on %s is deprecated since version 1.30 and will be removed in 2.0.', __CLASS__), E_USER_DEPRECATED);
28
- }
29
-
30
- if (function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) {
31
- $compiler->raw('twig_template_get_attributes($this, ');
32
- } else {
33
- $compiler->raw('$this->getAttribute(');
34
- }
35
-
36
- if ($this->getAttribute('ignore_strict_check')) {
37
- $this->getNode('node')->setAttribute('ignore_strict_check', true);
38
- }
39
-
40
- $compiler->subcompile($this->getNode('node'));
41
-
42
- $compiler->raw(', ')->subcompile($this->getNode('attribute'));
43
-
44
- // only generate optional arguments when needed (to make generated code more readable)
45
- $needFourth = $this->getAttribute('ignore_strict_check');
46
- $needThird = $needFourth || $this->getAttribute('is_defined_test');
47
- $needSecond = $needThird || Twig_Template::ANY_CALL !== $this->getAttribute('type');
48
- $needFirst = $needSecond || $this->hasNode('arguments');
49
-
50
- if ($needFirst) {
51
- if ($this->hasNode('arguments')) {
52
- $compiler->raw(', ')->subcompile($this->getNode('arguments'));
53
- } else {
54
- $compiler->raw(', []');
55
- }
56
- }
57
-
58
- if ($needSecond) {
59
- $compiler->raw(', ')->repr($this->getAttribute('type'));
60
- }
61
-
62
- if ($needThird) {
63
- $compiler->raw(', ')->repr($this->getAttribute('is_defined_test'));
64
- }
65
-
66
- if ($needFourth) {
67
- $compiler->raw(', ')->repr($this->getAttribute('ignore_strict_check'));
68
- }
69
-
70
- $compiler->raw(')');
71
  }
72
  }
73
-
74
- class_alias('Twig_Node_Expression_GetAttr', 'Twig\Node\Expression\GetAttrExpression', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\GetAttrExpression;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\GetAttrExpression');
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_GetAttr extends GetAttrExpression
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/MethodCall.php CHANGED
@@ -1,43 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_MethodCall extends Twig_Node_Expression
12
- {
13
- public function __construct(Twig_Node_Expression $node, $method, Twig_Node_Expression_Array $arguments, $lineno)
14
- {
15
- parent::__construct(['node' => $node, 'arguments' => $arguments], ['method' => $method, 'safe' => false], $lineno);
16
 
17
- if ($node instanceof Twig_Node_Expression_Name) {
18
- $node->setAttribute('always_defined', true);
19
- }
20
- }
21
 
22
- public function compile(Twig_Compiler $compiler)
 
23
  {
24
- $compiler
25
- ->subcompile($this->getNode('node'))
26
- ->raw('->')
27
- ->raw($this->getAttribute('method'))
28
- ->raw('(')
29
- ;
30
- $first = true;
31
- foreach ($this->getNode('arguments')->getKeyValuePairs() as $pair) {
32
- if (!$first) {
33
- $compiler->raw(', ');
34
- }
35
- $first = false;
36
-
37
- $compiler->subcompile($pair['value']);
38
- }
39
- $compiler->raw(')');
40
  }
41
  }
42
-
43
- class_alias('Twig_Node_Expression_MethodCall', 'Twig\Node\Expression\MethodCallExpression', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\MethodCallExpression;
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\MethodCallExpression');
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_MethodCall extends MethodCallExpression
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Name.php CHANGED
@@ -1,107 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Name extends Twig_Node_Expression
13
- {
14
- protected $specialVars = [
15
- '_self' => '$this',
16
- '_context' => '$context',
17
- '_charset' => '$this->env->getCharset()',
18
- ];
19
 
20
- public function __construct($name, $lineno)
21
- {
22
- parent::__construct([], ['name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false], $lineno);
23
- }
24
 
25
- public function compile(Twig_Compiler $compiler)
 
26
  {
27
- $name = $this->getAttribute('name');
28
-
29
- $compiler->addDebugInfo($this);
30
-
31
- if ($this->getAttribute('is_defined_test')) {
32
- if ($this->isSpecial()) {
33
- $compiler->repr(true);
34
- } else {
35
- $compiler
36
- ->raw('(isset($context[')
37
- ->string($name)
38
- ->raw(']) || array_key_exists(')
39
- ->string($name)
40
- ->raw(', $context))');
41
- }
42
- } elseif ($this->isSpecial()) {
43
- $compiler->raw($this->specialVars[$name]);
44
- } elseif ($this->getAttribute('always_defined')) {
45
- $compiler
46
- ->raw('$context[')
47
- ->string($name)
48
- ->raw(']')
49
- ;
50
- } else {
51
- if (PHP_VERSION_ID >= 70000) {
52
- // use PHP 7 null coalescing operator
53
- $compiler
54
- ->raw('($context[')
55
- ->string($name)
56
- ->raw('] ?? ')
57
- ;
58
-
59
- if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) {
60
- $compiler->raw('null)');
61
- } else {
62
- $compiler->raw('$this->getContext($context, ')->string($name)->raw('))');
63
- }
64
- } elseif (PHP_VERSION_ID >= 50400) {
65
- // PHP 5.4 ternary operator performance was optimized
66
- $compiler
67
- ->raw('(isset($context[')
68
- ->string($name)
69
- ->raw(']) ? $context[')
70
- ->string($name)
71
- ->raw('] : ')
72
- ;
73
-
74
- if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) {
75
- $compiler->raw('null)');
76
- } else {
77
- $compiler->raw('$this->getContext($context, ')->string($name)->raw('))');
78
- }
79
- } else {
80
- $compiler
81
- ->raw('$this->getContext($context, ')
82
- ->string($name)
83
- ;
84
-
85
- if ($this->getAttribute('ignore_strict_check')) {
86
- $compiler->raw(', true');
87
- }
88
-
89
- $compiler
90
- ->raw(')')
91
- ;
92
- }
93
- }
94
- }
95
-
96
- public function isSpecial()
97
- {
98
- return isset($this->specialVars[$this->getAttribute('name')]);
99
- }
100
-
101
- public function isSimple()
102
- {
103
- return !$this->isSpecial() && !$this->getAttribute('is_defined_test');
104
  }
105
  }
106
-
107
- class_alias('Twig_Node_Expression_Name', 'Twig\Node\Expression\NameExpression', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\NameExpression;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\NameExpression');
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_Name extends NameExpression
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/NullCoalesce.php CHANGED
@@ -1,48 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_NullCoalesce extends Twig_Node_Expression_Conditional
12
- {
13
- public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
14
- {
15
- $test = new Twig_Node_Expression_Binary_And(
16
- new Twig_Node_Expression_Test_Defined(clone $left, 'defined', new Twig_Node(), $left->getTemplateLine()),
17
- new Twig_Node_Expression_Unary_Not(new Twig_Node_Expression_Test_Null($left, 'null', new Twig_Node(), $left->getTemplateLine()), $left->getTemplateLine()),
18
- $left->getTemplateLine()
19
- );
20
 
21
- parent::__construct($test, $left, $right, $lineno);
22
- }
23
 
24
- public function compile(Twig_Compiler $compiler)
 
25
  {
26
- /*
27
- * This optimizes only one case. PHP 7 also supports more complex expressions
28
- * that can return null. So, for instance, if log is defined, log("foo") ?? "..." works,
29
- * but log($a["foo"]) ?? "..." does not if $a["foo"] is not defined. More advanced
30
- * cases might be implemented as an optimizer node visitor, but has not been done
31
- * as benefits are probably not worth the added complexity.
32
- */
33
- if (PHP_VERSION_ID >= 70000 && $this->getNode('expr2') instanceof Twig_Node_Expression_Name) {
34
- $this->getNode('expr2')->setAttribute('always_defined', true);
35
- $compiler
36
- ->raw('((')
37
- ->subcompile($this->getNode('expr2'))
38
- ->raw(') ?? (')
39
- ->subcompile($this->getNode('expr3'))
40
- ->raw('))')
41
- ;
42
- } else {
43
- parent::compile($compiler);
44
- }
45
  }
46
  }
47
-
48
- class_alias('Twig_Node_Expression_NullCoalesce', 'Twig\Node\Expression\NullCoalesceExpression', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\NullCoalesceExpression;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\NullCoalesceExpression');
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_NullCoalesce extends NullCoalesceExpression
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Parent.php CHANGED
@@ -1,44 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Represents a parent node.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- class Twig_Node_Expression_Parent extends Twig_Node_Expression
19
- {
20
- public function __construct($name, $lineno, $tag = null)
21
- {
22
- parent::__construct([], ['output' => false, 'name' => $name], $lineno, $tag);
23
- }
24
 
25
- public function compile(Twig_Compiler $compiler)
 
26
  {
27
- if ($this->getAttribute('output')) {
28
- $compiler
29
- ->addDebugInfo($this)
30
- ->write('$this->displayParentBlock(')
31
- ->string($this->getAttribute('name'))
32
- ->raw(", \$context, \$blocks);\n")
33
- ;
34
- } else {
35
- $compiler
36
- ->raw('$this->renderParentBlock(')
37
- ->string($this->getAttribute('name'))
38
- ->raw(', $context, $blocks)')
39
- ;
40
- }
41
  }
42
  }
43
-
44
- class_alias('Twig_Node_Expression_Parent', 'Twig\Node\Expression\ParentExpression', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\ParentExpression;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\ParentExpression');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_Parent extends ParentExpression
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/TempName.php CHANGED
@@ -1,28 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_TempName extends Twig_Node_Expression
12
- {
13
- public function __construct($name, $lineno)
14
- {
15
- parent::__construct([], ['name' => $name], $lineno);
16
- }
17
 
18
- public function compile(Twig_Compiler $compiler)
 
 
 
19
  {
20
- $compiler
21
- ->raw('$_')
22
- ->raw($this->getAttribute('name'))
23
- ->raw('_')
24
- ;
25
  }
26
  }
27
-
28
- class_alias('Twig_Node_Expression_TempName', 'Twig\Node\Expression\TempNameExpression', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\TempNameExpression;
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\TempNameExpression');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_TempName extends TempNameExpression
9
  {
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test.php CHANGED
@@ -1,45 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
- class Twig_Node_Expression_Test extends Twig_Node_Expression_Call
12
- {
13
- public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
14
- {
15
- $nodes = ['node' => $node];
16
- if (null !== $arguments) {
17
- $nodes['arguments'] = $arguments;
18
- }
19
 
20
- parent::__construct($nodes, ['name' => $name], $lineno);
21
- }
22
 
23
- public function compile(Twig_Compiler $compiler)
 
24
  {
25
- $name = $this->getAttribute('name');
26
- $test = $compiler->getEnvironment()->getTest($name);
27
-
28
- $this->setAttribute('name', $name);
29
- $this->setAttribute('type', 'test');
30
- $this->setAttribute('thing', $test);
31
- if ($test instanceof Twig_SimpleTest) {
32
- $this->setAttribute('arguments', $test->getArguments());
33
- }
34
- if ($test instanceof Twig_TestCallableInterface || $test instanceof Twig_SimpleTest) {
35
- $this->setAttribute('callable', $test->getCallable());
36
- }
37
- if ($test instanceof Twig_SimpleTest) {
38
- $this->setAttribute('is_variadic', $test->isVariadic());
39
- }
40
-
41
- $this->compileCallable($compiler);
42
  }
43
  }
44
-
45
- class_alias('Twig_Node_Expression_Test', 'Twig\Node\Expression\TestExpression', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\TestExpression;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\TestExpression');
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_Test extends TestExpression
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test/Constant.php CHANGED
@@ -1,48 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Checks if a variable is the exact same value as a constant.
14
- *
15
- * <pre>
16
- * {% if post.status is constant('Post::PUBLISHED') %}
17
- * the status attribute is exactly the same as Post::PUBLISHED
18
- * {% endif %}
19
- * </pre>
20
- *
21
- * @author Fabien Potencier <fabien@symfony.com>
22
- */
23
- class Twig_Node_Expression_Test_Constant extends Twig_Node_Expression_Test
24
- {
25
- public function compile(Twig_Compiler $compiler)
26
- {
27
- $compiler
28
- ->raw('(')
29
- ->subcompile($this->getNode('node'))
30
- ->raw(' === constant(')
31
- ;
32
-
33
- if ($this->getNode('arguments')->hasNode(1)) {
34
- $compiler
35
- ->raw('get_class(')
36
- ->subcompile($this->getNode('arguments')->getNode(1))
37
- ->raw(')."::".')
38
- ;
39
- }
40
 
41
- $compiler
42
- ->subcompile($this->getNode('arguments')->getNode(0))
43
- ->raw('))')
44
- ;
45
  }
46
  }
47
-
48
- class_alias('Twig_Node_Expression_Test_Constant', 'Twig\Node\Expression\Test\ConstantTest', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Test\ConstantTest;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Test\ConstantTest');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_Test_Constant extends ConstantTest
9
+ {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.php CHANGED
@@ -1,61 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Checks if a variable is defined in the current context.
14
- *
15
- * <pre>
16
- * {# defined works with variable names and variable attributes #}
17
- * {% if foo is defined %}
18
- * {# ... #}
19
- * {% endif %}
20
- * </pre>
21
- *
22
- * @author Fabien Potencier <fabien@symfony.com>
23
- */
24
- class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test
25
- {
26
- public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
27
- {
28
- if ($node instanceof Twig_Node_Expression_Name) {
29
- $node->setAttribute('is_defined_test', true);
30
- } elseif ($node instanceof Twig_Node_Expression_GetAttr) {
31
- $node->setAttribute('is_defined_test', true);
32
- $this->changeIgnoreStrictCheck($node);
33
- } elseif ($node instanceof Twig_Node_Expression_BlockReference) {
34
- $node->setAttribute('is_defined_test', true);
35
- } elseif ($node instanceof Twig_Node_Expression_Function && 'constant' === $node->getAttribute('name')) {
36
- $node->setAttribute('is_defined_test', true);
37
- } elseif ($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array) {
38
- $node = new Twig_Node_Expression_Constant(true, $node->getTemplateLine());
39
- } else {
40
- throw new Twig_Error_Syntax('The "defined" test only works with simple variables.', $this->getTemplateLine());
41
- }
42
-
43
- parent::__construct($node, $name, $arguments, $lineno);
44
- }
45
-
46
- protected function changeIgnoreStrictCheck(Twig_Node_Expression_GetAttr $node)
47
- {
48
- $node->setAttribute('ignore_strict_check', true);
49
-
50
- if ($node->getNode('node') instanceof Twig_Node_Expression_GetAttr) {
51
- $this->changeIgnoreStrictCheck($node->getNode('node'));
52
- }
53
- }
54
 
55
- public function compile(Twig_Compiler $compiler)
 
56
  {
57
- $compiler->subcompile($this->getNode('node'));
58
  }
59
  }
60
-
61
- class_alias('Twig_Node_Expression_Test_Defined', 'Twig\Node\Expression\Test\DefinedTest', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Test\DefinedTest;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Test\DefinedTest');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_Test_Defined extends DefinedTest
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test/Divisibleby.php CHANGED
@@ -1,35 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Checks if a variable is divisible by a number.
14
- *
15
- * <pre>
16
- * {% if loop.index is divisible by(3) %}
17
- * </pre>
18
- *
19
- * @author Fabien Potencier <fabien@symfony.com>
20
- */
21
- class Twig_Node_Expression_Test_Divisibleby extends Twig_Node_Expression_Test
22
- {
23
- public function compile(Twig_Compiler $compiler)
24
  {
25
- $compiler
26
- ->raw('(0 == ')
27
- ->subcompile($this->getNode('node'))
28
- ->raw(' % ')
29
- ->subcompile($this->getNode('arguments')->getNode(0))
30
- ->raw(')')
31
- ;
32
  }
33
  }
34
-
35
- class_alias('Twig_Node_Expression_Test_Divisibleby', 'Twig\Node\Expression\Test\DivisiblebyTest', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Test\DivisiblebyTest;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Test\DivisiblebyTest');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Test_Divisibleby extends DivisiblebyTest
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test/Even.php CHANGED
@@ -1,34 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Checks if a number is even.
14
- *
15
- * <pre>
16
- * {{ var is even }}
17
- * </pre>
18
- *
19
- * @author Fabien Potencier <fabien@symfony.com>
20
- */
21
- class Twig_Node_Expression_Test_Even extends Twig_Node_Expression_Test
22
- {
23
- public function compile(Twig_Compiler $compiler)
24
  {
25
- $compiler
26
- ->raw('(')
27
- ->subcompile($this->getNode('node'))
28
- ->raw(' % 2 == 0')
29
- ->raw(')')
30
- ;
31
  }
32
  }
33
-
34
- class_alias('Twig_Node_Expression_Test_Even', 'Twig\Node\Expression\Test\EvenTest', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Test\EvenTest;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Test\EvenTest');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Test_Even extends EvenTest
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test/Null.php CHANGED
@@ -1,33 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Checks that a variable is null.
14
- *
15
- * <pre>
16
- * {{ var is none }}
17
- * </pre>
18
- *
19
- * @author Fabien Potencier <fabien@symfony.com>
20
- */
21
- class Twig_Node_Expression_Test_Null extends Twig_Node_Expression_Test
22
- {
23
- public function compile(Twig_Compiler $compiler)
24
  {
25
- $compiler
26
- ->raw('(null === ')
27
- ->subcompile($this->getNode('node'))
28
- ->raw(')')
29
- ;
30
  }
31
  }
32
-
33
- class_alias('Twig_Node_Expression_Test_Null', 'Twig\Node\Expression\Test\NullTest', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Test\NullTest;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Test\NullTest');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Test_Null extends NullTest
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test/Odd.php CHANGED
@@ -1,34 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Checks if a number is odd.
14
- *
15
- * <pre>
16
- * {{ var is odd }}
17
- * </pre>
18
- *
19
- * @author Fabien Potencier <fabien@symfony.com>
20
- */
21
- class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test
22
- {
23
- public function compile(Twig_Compiler $compiler)
24
  {
25
- $compiler
26
- ->raw('(')
27
- ->subcompile($this->getNode('node'))
28
- ->raw(' % 2 == 1')
29
- ->raw(')')
30
- ;
31
  }
32
  }
33
-
34
- class_alias('Twig_Node_Expression_Test_Odd', 'Twig\Node\Expression\Test\OddTest', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Test\OddTest;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Test\OddTest');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Test_Odd extends OddTest
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Test/Sameas.php CHANGED
@@ -1,31 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Checks if a variable is the same as another one (=== in PHP).
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Node_Expression_Test_Sameas extends Twig_Node_Expression_Test
18
- {
19
- public function compile(Twig_Compiler $compiler)
20
  {
21
- $compiler
22
- ->raw('(')
23
- ->subcompile($this->getNode('node'))
24
- ->raw(' === ')
25
- ->subcompile($this->getNode('arguments')->getNode(0))
26
- ->raw(')')
27
- ;
28
  }
29
  }
30
-
31
- class_alias('Twig_Node_Expression_Test_Sameas', 'Twig\Node\Expression\Test\SameasTest', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Test\SameasTest;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\Expression\Test\SameasTest');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Test_Sameas extends SameasTest
 
 
 
 
9
  {
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Unary.php CHANGED
@@ -1,29 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- abstract class Twig_Node_Expression_Unary extends Twig_Node_Expression
13
- {
14
- public function __construct(Twig_NodeInterface $node, $lineno)
15
- {
16
- parent::__construct(['node' => $node], [], $lineno);
17
- }
18
 
19
- public function compile(Twig_Compiler $compiler)
 
20
  {
21
- $compiler->raw(' ');
22
- $this->operator($compiler);
23
- $compiler->subcompile($this->getNode('node'));
24
  }
25
-
26
- abstract public function operator(Twig_Compiler $compiler);
27
  }
28
-
29
- class_alias('Twig_Node_Expression_Unary', 'Twig\Node\Expression\Unary\AbstractUnary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Unary\AbstractUnary;
4
+
5
+ class_exists('Twig\Node\Expression\Unary\AbstractUnary');
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Expression_Unary extends AbstractUnary
9
  {
 
 
 
10
  }
 
 
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Neg.php CHANGED
@@ -1,20 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Unary_Neg extends Twig_Node_Expression_Unary
13
- {
14
- public function operator(Twig_Compiler $compiler)
15
  {
16
- $compiler->raw('-');
17
  }
18
  }
19
-
20
- class_alias('Twig_Node_Expression_Unary_Neg', 'Twig\Node\Expression\Unary\NegUnary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Unary\NegUnary;
4
+
5
+ class_exists('Twig\Node\Expression\Unary\NegUnary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Unary_Neg extends NegUnary
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Not.php CHANGED
@@ -1,20 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Unary_Not extends Twig_Node_Expression_Unary
13
- {
14
- public function operator(Twig_Compiler $compiler)
15
  {
16
- $compiler->raw('!');
17
  }
18
  }
19
-
20
- class_alias('Twig_Node_Expression_Unary_Not', 'Twig\Node\Expression\Unary\NotUnary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Unary\NotUnary;
4
+
5
+ class_exists('Twig\Node\Expression\Unary\NotUnary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Unary_Not extends NotUnary
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Pos.php CHANGED
@@ -1,20 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
8
- *
9
- * For the full copyright and license information, please view the LICENSE
10
- * file that was distributed with this source code.
11
- */
12
- class Twig_Node_Expression_Unary_Pos extends Twig_Node_Expression_Unary
13
- {
14
- public function operator(Twig_Compiler $compiler)
15
  {
16
- $compiler->raw('+');
17
  }
18
  }
19
-
20
- class_alias('Twig_Node_Expression_Unary_Pos', 'Twig\Node\Expression\Unary\PosUnary', false);
1
  <?php
2
 
3
+ use Twig\Node\Expression\Unary\PosUnary;
4
+
5
+ class_exists('Twig\Node\Expression\Unary\PosUnary');
6
+
7
+ if (\false) {
8
+ class Twig_Node_Expression_Unary_Pos extends PosUnary
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Flush.php CHANGED
@@ -1,33 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a flush node.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Node_Flush extends Twig_Node
18
- {
19
- public function __construct($lineno, $tag)
20
- {
21
- parent::__construct([], [], $lineno, $tag);
22
- }
23
 
24
- public function compile(Twig_Compiler $compiler)
 
25
  {
26
- $compiler
27
- ->addDebugInfo($this)
28
- ->write("flush();\n")
29
- ;
30
  }
31
  }
32
-
33
- class_alias('Twig_Node_Flush', 'Twig\Node\FlushNode', false);
1
  <?php
2
 
3
+ use Twig\Node\FlushNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\FlushNode');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Flush extends FlushNode
9
  {
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/For.php CHANGED
@@ -1,113 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Represents a for node.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- class Twig_Node_For extends Twig_Node
19
- {
20
- protected $loop;
21
 
22
- public function __construct(Twig_Node_Expression_AssignName $keyTarget, Twig_Node_Expression_AssignName $valueTarget, Twig_Node_Expression $seq, Twig_Node_Expression $ifexpr = null, Twig_NodeInterface $body, Twig_NodeInterface $else = null, $lineno, $tag = null)
 
23
  {
24
- $body = new Twig_Node([$body, $this->loop = new Twig_Node_ForLoop($lineno, $tag)]);
25
-
26
- if (null !== $ifexpr) {
27
- $body = new Twig_Node_If(new Twig_Node([$ifexpr, $body]), null, $lineno, $tag);
28
- }
29
-
30
- $nodes = ['key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body];
31
- if (null !== $else) {
32
- $nodes['else'] = $else;
33
- }
34
-
35
- parent::__construct($nodes, ['with_loop' => true, 'ifexpr' => null !== $ifexpr], $lineno, $tag);
36
- }
37
-
38
- public function compile(Twig_Compiler $compiler)
39
- {
40
- $compiler
41
- ->addDebugInfo($this)
42
- ->write("\$context['_parent'] = \$context;\n")
43
- ->write("\$context['_seq'] = twig_ensure_traversable(")
44
- ->subcompile($this->getNode('seq'))
45
- ->raw(");\n")
46
- ;
47
-
48
- if ($this->hasNode('else')) {
49
- $compiler->write("\$context['_iterated'] = false;\n");
50
- }
51
-
52
- if ($this->getAttribute('with_loop')) {
53
- $compiler
54
- ->write("\$context['loop'] = [\n")
55
- ->write(" 'parent' => \$context['_parent'],\n")
56
- ->write(" 'index0' => 0,\n")
57
- ->write(" 'index' => 1,\n")
58
- ->write(" 'first' => true,\n")
59
- ->write("];\n")
60
- ;
61
-
62
- if (!$this->getAttribute('ifexpr')) {
63
- $compiler
64
- ->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable)) {\n")
65
- ->indent()
66
- ->write("\$length = count(\$context['_seq']);\n")
67
- ->write("\$context['loop']['revindex0'] = \$length - 1;\n")
68
- ->write("\$context['loop']['revindex'] = \$length;\n")
69
- ->write("\$context['loop']['length'] = \$length;\n")
70
- ->write("\$context['loop']['last'] = 1 === \$length;\n")
71
- ->outdent()
72
- ->write("}\n")
73
- ;
74
- }
75
- }
76
-
77
- $this->loop->setAttribute('else', $this->hasNode('else'));
78
- $this->loop->setAttribute('with_loop', $this->getAttribute('with_loop'));
79
- $this->loop->setAttribute('ifexpr', $this->getAttribute('ifexpr'));
80
-
81
- $compiler
82
- ->write("foreach (\$context['_seq'] as ")
83
- ->subcompile($this->getNode('key_target'))
84
- ->raw(' => ')
85
- ->subcompile($this->getNode('value_target'))
86
- ->raw(") {\n")
87
- ->indent()
88
- ->subcompile($this->getNode('body'))
89
- ->outdent()
90
- ->write("}\n")
91
- ;
92
-
93
- if ($this->hasNode('else')) {
94
- $compiler
95
- ->write("if (!\$context['_iterated']) {\n")
96
- ->indent()
97
- ->subcompile($this->getNode('else'))
98
- ->outdent()
99
- ->write("}\n")
100
- ;
101
- }
102
-
103
- $compiler->write("\$_parent = \$context['_parent'];\n");
104
-
105
- // remove some "private" loop variables (needed for nested loops)
106
- $compiler->write('unset($context[\'_seq\'], $context[\'_iterated\'], $context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'_parent\'], $context[\'loop\']);'."\n");
107
-
108
- // keep the values set in the inner context for variables defined in the outer context
109
- $compiler->write("\$context = array_intersect_key(\$context, \$_parent) + \$_parent;\n");
110
  }
111
  }
112
-
113
- class_alias('Twig_Node_For', 'Twig\Node\ForNode', false);
1
  <?php
2
 
3
+ use Twig\Node\ForNode;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\ForNode');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_For extends ForNode
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/ForLoop.php CHANGED
@@ -1,52 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Internal node used by the for node.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Node_ForLoop extends Twig_Node
18
- {
19
- public function __construct($lineno, $tag = null)
20
- {
21
- parent::__construct([], ['with_loop' => false, 'ifexpr' => false, 'else' => false], $lineno, $tag);
22
- }
23
 
24
- public function compile(Twig_Compiler $compiler)
 
25
  {
26
- if ($this->getAttribute('else')) {
27
- $compiler->write("\$context['_iterated'] = true;\n");
28
- }
29
-
30
- if ($this->getAttribute('with_loop')) {
31
- $compiler
32
- ->write("++\$context['loop']['index0'];\n")
33
- ->write("++\$context['loop']['index'];\n")
34
- ->write("\$context['loop']['first'] = false;\n")
35
- ;
36
-
37
- if (!$this->getAttribute('ifexpr')) {
38
- $compiler
39
- ->write("if (isset(\$context['loop']['length'])) {\n")
40
- ->indent()
41
- ->write("--\$context['loop']['revindex0'];\n")
42
- ->write("--\$context['loop']['revindex'];\n")
43
- ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n")
44
- ->outdent()
45
- ->write("}\n")
46
- ;
47
- }
48
- }
49
  }
50
  }
51
-
52
- class_alias('Twig_Node_ForLoop', 'Twig\Node\ForLoopNode', false);
1
  <?php
2
 
3
+ use Twig\Node\ForLoopNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\ForLoopNode');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_ForLoop extends ForLoopNode
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/If.php CHANGED
@@ -1,68 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Represents an if node.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- class Twig_Node_If extends Twig_Node
19
- {
20
- public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else = null, $lineno, $tag = null)
21
- {
22
- $nodes = ['tests' => $tests];
23
- if (null !== $else) {
24
- $nodes['else'] = $else;
25
- }
26
-
27
- parent::__construct($nodes, [], $lineno, $tag);
28
- }
29
 
30
- public function compile(Twig_Compiler $compiler)
 
31
  {
32
- $compiler->addDebugInfo($this);
33
- for ($i = 0, $count = count($this->getNode('tests')); $i < $count; $i += 2) {
34
- if ($i > 0) {
35
- $compiler
36
- ->outdent()
37
- ->write('} elseif (')
38
- ;
39
- } else {
40
- $compiler
41
- ->write('if (')
42
- ;
43
- }
44
-
45
- $compiler
46
- ->subcompile($this->getNode('tests')->getNode($i))
47
- ->raw(") {\n")
48
- ->indent()
49
- ->subcompile($this->getNode('tests')->getNode($i + 1))
50
- ;
51
- }
52
-
53
- if ($this->hasNode('else')) {
54
- $compiler
55
- ->outdent()
56
- ->write("} else {\n")
57
- ->indent()
58
- ->subcompile($this->getNode('else'))
59
- ;
60
- }
61
-
62
- $compiler
63
- ->outdent()
64
- ->write("}\n");
65
  }
66
  }
67
-
68
- class_alias('Twig_Node_If', 'Twig\Node\IfNode', false);
1
  <?php
2
 
3
+ use Twig\Node\IfNode;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\IfNode');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_If extends IfNode
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Import.php CHANGED
@@ -1,51 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents an import node.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Node_Import extends Twig_Node
18
- {
19
- public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $var, $lineno, $tag = null)
20
- {
21
- parent::__construct(['expr' => $expr, 'var' => $var], [], $lineno, $tag);
22
- }
23
 
24
- public function compile(Twig_Compiler $compiler)
 
25
  {
26
- $compiler
27
- ->addDebugInfo($this)
28
- ->write('')
29
- ->subcompile($this->getNode('var'))
30
- ->raw(' = ')
31
- ;
32
-
33
- if ($this->getNode('expr') instanceof Twig_Node_Expression_Name && '_self' === $this->getNode('expr')->getAttribute('name')) {
34
- $compiler->raw('$this');
35
- } else {
36
- $compiler
37
- ->raw('$this->loadTemplate(')
38
- ->subcompile($this->getNode('expr'))
39
- ->raw(', ')
40
- ->repr($this->getTemplateName())
41
- ->raw(', ')
42
- ->repr($this->getTemplateLine())
43
- ->raw(')')
44
- ;
45
- }
46
-
47
- $compiler->raw(";\n");
48
  }
49
  }
50
-
51
- class_alias('Twig_Node_Import', 'Twig\Node\ImportNode', false);
1
  <?php
2
 
3
+ use Twig\Node\ImportNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\ImportNode');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Import extends ImportNode
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Include.php CHANGED
@@ -1,90 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Represents an include node.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface
19
- {
20
- public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
21
- {
22
- $nodes = ['expr' => $expr];
23
- if (null !== $variables) {
24
- $nodes['variables'] = $variables;
25
- }
26
-
27
- parent::__construct($nodes, ['only' => (bool) $only, 'ignore_missing' => (bool) $ignoreMissing], $lineno, $tag);
28
- }
29
-
30
- public function compile(Twig_Compiler $compiler)
31
- {
32
- $compiler->addDebugInfo($this);
33
-
34
- if ($this->getAttribute('ignore_missing')) {
35
- $compiler
36
- ->write("try {\n")
37
- ->indent()
38
- ;
39
- }
40
-
41
- $this->addGetTemplate($compiler);
42
-
43
- $compiler->raw('->display(');
44
 
45
- $this->addTemplateArguments($compiler);
46
-
47
- $compiler->raw(");\n");
48
-
49
- if ($this->getAttribute('ignore_missing')) {
50
- $compiler
51
- ->outdent()
52
- ->write("} catch (Twig_Error_Loader \$e) {\n")
53
- ->indent()
54
- ->write("// ignore missing template\n")
55
- ->outdent()
56
- ->write("}\n\n")
57
- ;
58
- }
59
- }
60
-
61
- protected function addGetTemplate(Twig_Compiler $compiler)
62
  {
63
- $compiler
64
- ->write('$this->loadTemplate(')
65
- ->subcompile($this->getNode('expr'))
66
- ->raw(', ')
67
- ->repr($this->getTemplateName())
68
- ->raw(', ')
69
- ->repr($this->getTemplateLine())
70
- ->raw(')')
71
- ;
72
- }
73
-
74
- protected function addTemplateArguments(Twig_Compiler $compiler)
75
- {
76
- if (!$this->hasNode('variables')) {
77
- $compiler->raw(false === $this->getAttribute('only') ? '$context' : '[]');
78
- } elseif (false === $this->getAttribute('only')) {
79
- $compiler
80
- ->raw('array_merge($context, ')
81
- ->subcompile($this->getNode('variables'))
82
- ->raw(')')
83
- ;
84
- } else {
85
- $compiler->subcompile($this->getNode('variables'));
86
- }
87
  }
88
  }
89
-
90
- class_alias('Twig_Node_Include', 'Twig\Node\IncludeNode', false);
1
  <?php
2
 
3
+ use Twig\Node\IncludeNode;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\IncludeNode');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Include extends IncludeNode
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Macro.php CHANGED
@@ -1,125 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a macro node.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Node_Macro extends Twig_Node
18
- {
19
- const VARARGS_NAME = 'varargs';
20
 
21
- public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null)
 
22
  {
23
- foreach ($arguments as $argumentName => $argument) {
24
- if (self::VARARGS_NAME === $argumentName) {
25
- throw new Twig_Error_Syntax(sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.', self::VARARGS_NAME, $name, self::VARARGS_NAME), $argument->getTemplateLine());
26
- }
27
- }
28
-
29
- parent::__construct(['body' => $body, 'arguments' => $arguments], ['name' => $name], $lineno, $tag);
30
- }
31
-
32
- public function compile(Twig_Compiler $compiler)
33
- {
34
- $compiler
35
- ->addDebugInfo($this)
36
- ->write(sprintf('public function get%s(', $this->getAttribute('name')))
37
- ;
38
-
39
- $count = count($this->getNode('arguments'));
40
- $pos = 0;
41
- foreach ($this->getNode('arguments') as $name => $default) {
42
- $compiler
43
- ->raw('$__'.$name.'__ = ')
44
- ->subcompile($default)
45
- ;
46
-
47
- if (++$pos < $count) {
48
- $compiler->raw(', ');
49
- }
50
- }
51
-
52
- if (PHP_VERSION_ID >= 50600) {
53
- if ($count) {
54
- $compiler->raw(', ');
55
- }
56
-
57
- $compiler->raw('...$__varargs__');
58
- }
59
-
60
- $compiler
61
- ->raw(")\n")
62
- ->write("{\n")
63
- ->indent()
64
- ;
65
-
66
- $compiler
67
- ->write("\$context = \$this->env->mergeGlobals([\n")
68
- ->indent()
69
- ;
70
-
71
- foreach ($this->getNode('arguments') as $name => $default) {
72
- $compiler
73
- ->write('')
74
- ->string($name)
75
- ->raw(' => $__'.$name.'__')
76
- ->raw(",\n")
77
- ;
78
- }
79
-
80
- $compiler
81
- ->write('')
82
- ->string(self::VARARGS_NAME)
83
- ->raw(' => ')
84
- ;
85
-
86
- if (PHP_VERSION_ID >= 50600) {
87
- $compiler->raw("\$__varargs__,\n");
88
- } else {
89
- $compiler
90
- ->raw('func_num_args() > ')
91
- ->repr($count)
92
- ->raw(' ? array_slice(func_get_args(), ')
93
- ->repr($count)
94
- ->raw(") : [],\n")
95
- ;
96
- }
97
-
98
- $compiler
99
- ->outdent()
100
- ->write("]);\n\n")
101
- ->write("\$blocks = [];\n\n")
102
- ->write("ob_start();\n")
103
- ->write("try {\n")
104
- ->indent()
105
- ->subcompile($this->getNode('body'))
106
- ->outdent()
107
- ->write("} catch (Exception \$e) {\n")
108
- ->indent()
109
- ->write("ob_end_clean();\n\n")
110
- ->write("throw \$e;\n")
111
- ->outdent()
112
- ->write("} catch (Throwable \$e) {\n")
113
- ->indent()
114
- ->write("ob_end_clean();\n\n")
115
- ->write("throw \$e;\n")
116
- ->outdent()
117
- ->write("}\n\n")
118
- ->write("return ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset());\n")
119
- ->outdent()
120
- ->write("}\n\n")
121
- ;
122
  }
123
  }
124
-
125
- class_alias('Twig_Node_Macro', 'Twig\Node\MacroNode', false);
1
  <?php
2
 
3
+ use Twig\Node\MacroNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\MacroNode');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Macro extends MacroNode
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Module.php CHANGED
@@ -1,466 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Represents a module node.
15
- *
16
- * Consider this class as being final. If you need to customize the behavior of
17
- * the generated class, consider adding nodes to the following nodes: display_start,
18
- * display_end, constructor_start, constructor_end, and class_end.
19
- *
20
- * @author Fabien Potencier <fabien@symfony.com>
21
- */
22
- class Twig_Node_Module extends Twig_Node
23
- {
24
- private $source;
25
 
26
- public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $name, $source = '')
 
27
  {
28
- if (!$name instanceof Twig_Source) {
29
- @trigger_error(sprintf('Passing a string as the $name argument of %s() is deprecated since version 1.27. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED);
30
- $this->source = new Twig_Source($source, $name);
31
- } else {
32
- $this->source = $name;
33
- }
34
-
35
- $nodes = [
36
- 'body' => $body,
37
- 'blocks' => $blocks,
38
- 'macros' => $macros,
39
- 'traits' => $traits,
40
- 'display_start' => new Twig_Node(),
41
- 'display_end' => new Twig_Node(),
42
- 'constructor_start' => new Twig_Node(),
43
- 'constructor_end' => new Twig_Node(),
44
- 'class_end' => new Twig_Node(),
45
- ];
46
- if (null !== $parent) {
47
- $nodes['parent'] = $parent;
48
- }
49
-
50
- // embedded templates are set as attributes so that they are only visited once by the visitors
51
- parent::__construct($nodes, [
52
- // source to be remove in 2.0
53
- 'source' => $this->source->getCode(),
54
- // filename to be remove in 2.0 (use getTemplateName() instead)
55
- 'filename' => $this->source->getName(),
56
- 'index' => null,
57
- 'embedded_templates' => $embeddedTemplates,
58
- ], 1);
59
-
60
- // populate the template name of all node children
61
- $this->setTemplateName($this->source->getName());
62
- }
63
-
64
- public function setIndex($index)
65
- {
66
- $this->setAttribute('index', $index);
67
- }
68
-
69
- public function compile(Twig_Compiler $compiler)
70
- {
71
- $this->compileTemplate($compiler);
72
-
73
- foreach ($this->getAttribute('embedded_templates') as $template) {
74
- $compiler->subcompile($template);
75
- }
76
- }
77
-
78
- protected function compileTemplate(Twig_Compiler $compiler)
79
- {
80
- if (!$this->getAttribute('index')) {
81
- $compiler->write('<?php');
82
- }
83
-
84
- $this->compileClassHeader($compiler);
85
-
86
- if (
87
- count($this->getNode('blocks'))
88
- || count($this->getNode('traits'))
89
- || !$this->hasNode('parent')
90
- || $this->getNode('parent') instanceof Twig_Node_Expression_Constant
91
- || count($this->getNode('constructor_start'))
92
- || count($this->getNode('constructor_end'))
93
- ) {
94
- $this->compileConstructor($compiler);
95
- }
96
-
97
- $this->compileGetParent($compiler);
98
-
99
- $this->compileDisplay($compiler);
100
-
101
- $compiler->subcompile($this->getNode('blocks'));
102
-
103
- $this->compileMacros($compiler);
104
-
105
- $this->compileGetTemplateName($compiler);
106
-
107
- $this->compileIsTraitable($compiler);
108
-
109
- $this->compileDebugInfo($compiler);
110
-
111
- $this->compileGetSource($compiler);
112
-
113
- $this->compileGetSourceContext($compiler);
114
-
115
- $this->compileClassFooter($compiler);
116
- }
117
-
118
- protected function compileGetParent(Twig_Compiler $compiler)
119
- {
120
- if (!$this->hasNode('parent')) {
121
- return;
122
- }
123
- $parent = $this->getNode('parent');
124
-
125
- $compiler
126
- ->write("protected function doGetParent(array \$context)\n", "{\n")
127
- ->indent()
128
- ->addDebugInfo($parent)
129
- ->write('return ')
130
- ;
131
-
132
- if ($parent instanceof Twig_Node_Expression_Constant) {
133
- $compiler->subcompile($parent);
134
- } else {
135
- $compiler
136
- ->raw('$this->loadTemplate(')
137
- ->subcompile($parent)
138
- ->raw(', ')
139
- ->repr($this->source->getName())
140
- ->raw(', ')
141
- ->repr($parent->getTemplateLine())
142
- ->raw(')')
143
- ;
144
- }
145
-
146
- $compiler
147
- ->raw(";\n")
148
- ->outdent()
149
- ->write("}\n\n")
150
- ;
151
- }
152
-
153
- protected function compileClassHeader(Twig_Compiler $compiler)
154
- {
155
- $compiler
156
- ->write("\n\n")
157
- // if the template name contains */, add a blank to avoid a PHP parse error
158
- ->write('/* '.str_replace('*/', '* /', $this->source->getName())." */\n")
159
- ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->source->getName(), $this->getAttribute('index')))
160
- ->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
161
- ->write("{\n")
162
- ->indent()
163
- ;
164
- }
165
-
166
- protected function compileConstructor(Twig_Compiler $compiler)
167
- {
168
- $compiler
169
- ->write("public function __construct(Twig_Environment \$env)\n", "{\n")
170
- ->indent()
171
- ->subcompile($this->getNode('constructor_start'))
172
- ->write("parent::__construct(\$env);\n\n")
173
- ;
174
-
175
- // parent
176
- if (!$this->hasNode('parent')) {
177
- $compiler->write("\$this->parent = false;\n\n");
178
- } elseif (($parent = $this->getNode('parent')) && $parent instanceof Twig_Node_Expression_Constant) {
179
- $compiler
180
- ->addDebugInfo($parent)
181
- ->write('$this->parent = $this->loadTemplate(')
182
- ->subcompile($parent)
183
- ->raw(', ')
184
- ->repr($this->source->getName())
185
- ->raw(', ')
186
- ->repr($parent->getTemplateLine())
187
- ->raw(");\n")
188
- ;
189
- }
190
-
191
- $countTraits = count($this->getNode('traits'));
192
- if ($countTraits) {
193
- // traits
194
- foreach ($this->getNode('traits') as $i => $trait) {
195
- $this->compileLoadTemplate($compiler, $trait->getNode('template'), sprintf('$_trait_%s', $i));
196
-
197
- $compiler
198
- ->addDebugInfo($trait->getNode('template'))
199
- ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i))
200
- ->indent()
201
- ->write("throw new Twig_Error_Runtime('Template \"'.")
202
- ->subcompile($trait->getNode('template'))
203
- ->raw(".'\" cannot be used as a trait.');\n")
204
- ->outdent()
205
- ->write("}\n")
206
- ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i))
207
- ;
208
-
209
- foreach ($trait->getNode('targets') as $key => $value) {
210
- $compiler
211
- ->write(sprintf('if (!isset($_trait_%s_blocks[', $i))
212
- ->string($key)
213
- ->raw("])) {\n")
214
- ->indent()
215
- ->write("throw new Twig_Error_Runtime(sprintf('Block ")
216
- ->string($key)
217
- ->raw(' is not defined in trait ')
218
- ->subcompile($trait->getNode('template'))
219
- ->raw(".'));\n")
220
- ->outdent()
221
- ->write("}\n\n")
222
-
223
- ->write(sprintf('$_trait_%s_blocks[', $i))
224
- ->subcompile($value)
225
- ->raw(sprintf('] = $_trait_%s_blocks[', $i))
226
- ->string($key)
227
- ->raw(sprintf(']; unset($_trait_%s_blocks[', $i))
228
- ->string($key)
229
- ->raw("]);\n\n")
230
- ;
231
- }
232
- }
233
-
234
- if ($countTraits > 1) {
235
- $compiler
236
- ->write("\$this->traits = array_merge(\n")
237
- ->indent()
238
- ;
239
-
240
- for ($i = 0; $i < $countTraits; ++$i) {
241
- $compiler
242
- ->write(sprintf('$_trait_%s_blocks'.($i == $countTraits - 1 ? '' : ',')."\n", $i))
243
- ;
244
- }
245
-
246
- $compiler
247
- ->outdent()
248
- ->write(");\n\n")
249
- ;
250
- } else {
251
- $compiler
252
- ->write("\$this->traits = \$_trait_0_blocks;\n\n")
253
- ;
254
- }
255
-
256
- $compiler
257
- ->write("\$this->blocks = array_merge(\n")
258
- ->indent()
259
- ->write("\$this->traits,\n")
260
- ->write("[\n")
261
- ;
262
- } else {
263
- $compiler
264
- ->write("\$this->blocks = [\n")
265
- ;
266
- }
267
-
268
- // blocks
269
- $compiler
270
- ->indent()
271
- ;
272
-
273
- foreach ($this->getNode('blocks') as $name => $node) {
274
- $compiler
275
- ->write(sprintf("'%s' => [\$this, 'block_%s'],\n", $name, $name))
276
- ;
277
- }
278
-
279
- if ($countTraits) {
280
- $compiler
281
- ->outdent()
282
- ->write("]\n")
283
- ->outdent()
284
- ->write(");\n")
285
- ;
286
- } else {
287
- $compiler
288
- ->outdent()
289
- ->write("];\n")
290
- ;
291
- }
292
-
293
- $compiler
294
- ->outdent()
295
- ->subcompile($this->getNode('constructor_end'))
296
- ->write("}\n\n")
297
- ;
298
- }
299
-
300
- protected function compileDisplay(Twig_Compiler $compiler)
301
- {
302
- $compiler
303
- ->write("protected function doDisplay(array \$context, array \$blocks = [])\n", "{\n")
304
- ->indent()
305
- ->subcompile($this->getNode('display_start'))
306
- ->subcompile($this->getNode('body'))
307
- ;
308
-
309
- if ($this->hasNode('parent')) {
310
- $parent = $this->getNode('parent');
311
- $compiler->addDebugInfo($parent);
312
- if ($parent instanceof Twig_Node_Expression_Constant) {
313
- $compiler->write('$this->parent');
314
- } else {
315
- $compiler->write('$this->getParent($context)');
316
- }
317
- $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n");
318
- }
319
-
320
- $compiler
321
- ->subcompile($this->getNode('display_end'))
322
- ->outdent()
323
- ->write("}\n\n")
324
- ;
325
- }
326
-
327
- protected function compileClassFooter(Twig_Compiler $compiler)
328
- {
329
- $compiler
330
- ->subcompile($this->getNode('class_end'))
331
- ->outdent()
332
- ->write("}\n")
333
- ;
334
- }
335
-
336
- protected function compileMacros(Twig_Compiler $compiler)
337
- {
338
- $compiler->subcompile($this->getNode('macros'));
339
- }
340
-
341
- protected function compileGetTemplateName(Twig_Compiler $compiler)
342
- {
343
- $compiler
344
- ->write("public function getTemplateName()\n", "{\n")
345
- ->indent()
346
- ->write('return ')
347
- ->repr($this->source->getName())
348
- ->raw(";\n")
349
- ->outdent()
350
- ->write("}\n\n")
351
- ;
352
- }
353
-
354
- protected function compileIsTraitable(Twig_Compiler $compiler)
355
- {
356
- // A template can be used as a trait if:
357
- // * it has no parent
358
- // * it has no macros
359
- // * it has no body
360
- //
361
- // Put another way, a template can be used as a trait if it
362
- // only contains blocks and use statements.
363
- $traitable = !$this->hasNode('parent') && 0 === count($this->getNode('macros'));
364
- if ($traitable) {
365
- if ($this->getNode('body') instanceof Twig_Node_Body) {
366
- $nodes = $this->getNode('body')->getNode(0);
367
- } else {
368
- $nodes = $this->getNode('body');
369
- }
370
-
371
- if (!count($nodes)) {
372
- $nodes = new Twig_Node([$nodes]);
373
- }
374
-
375
- foreach ($nodes as $node) {
376
- if (!count($node)) {
377
- continue;
378
- }
379
-
380
- if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) {
381
- continue;
382
- }
383
-
384
- if ($node instanceof Twig_Node_BlockReference) {
385
- continue;
386
- }
387
-
388
- $traitable = false;
389
- break;
390
- }
391
- }
392
-
393
- if ($traitable) {
394
- return;
395
- }
396
-
397
- $compiler
398
- ->write("public function isTraitable()\n", "{\n")
399
- ->indent()
400
- ->write(sprintf("return %s;\n", $traitable ? 'true' : 'false'))
401
- ->outdent()
402
- ->write("}\n\n")
403
- ;
404
- }
405
-
406
- protected function compileDebugInfo(Twig_Compiler $compiler)
407
- {
408
- $compiler
409
- ->write("public function getDebugInfo()\n", "{\n")
410
- ->indent()
411
- ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true))))
412
- ->outdent()
413
- ->write("}\n\n")
414
- ;
415
- }
416
-
417
- protected function compileGetSource(Twig_Compiler $compiler)
418
- {
419
- $compiler
420
- ->write("/** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */\n")
421
- ->write("public function getSource()\n", "{\n")
422
- ->indent()
423
- ->write("@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED);\n\n")
424
- ->write('return $this->getSourceContext()->getCode();')
425
- ->raw("\n")
426
- ->outdent()
427
- ->write("}\n\n")
428
- ;
429
- }
430
-
431
- protected function compileGetSourceContext(Twig_Compiler $compiler)
432
- {
433
- $compiler
434
- ->write("public function getSourceContext()\n", "{\n")
435
- ->indent()
436
- ->write('return new Twig_Source(')
437
- ->string($compiler->getEnvironment()->isDebug() ? $this->source->getCode() : '')
438
- ->raw(', ')
439
- ->string($this->source->getName())
440
- ->raw(', ')
441
- ->string($this->source->getPath())
442
- ->raw(");\n")
443
- ->outdent()
444
- ->write("}\n")
445
- ;
446
- }
447
-
448
- protected function compileLoadTemplate(Twig_Compiler $compiler, $node, $var)
449
- {
450
- if ($node instanceof Twig_Node_Expression_Constant) {
451
- $compiler
452
- ->write(sprintf('%s = $this->loadTemplate(', $var))
453
- ->subcompile($node)
454
- ->raw(', ')
455
- ->repr($node->getTemplateName())
456
- ->raw(', ')
457
- ->repr($node->getTemplateLine())
458
- ->raw(");\n")
459
- ;
460
- } else {
461
- throw new LogicException('Trait templates can only be constant nodes.');
462
- }
463
  }
464
  }
465
-
466
- class_alias('Twig_Node_Module', 'Twig\Node\ModuleNode', false);
1
  <?php
2
 
3
+ use Twig\Node\ModuleNode;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\ModuleNode');
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Module extends ModuleNode
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Print.php CHANGED
@@ -1,36 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Represents a node that outputs an expression.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface
19
- {
20
- public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null)
21
- {
22
- parent::__construct(['expr' => $expr], [], $lineno, $tag);
23
- }
24
 
25
- public function compile(Twig_Compiler $compiler)
 
26
  {
27
- $compiler
28
- ->addDebugInfo($this)
29
- ->write('echo ')
30
- ->subcompile($this->getNode('expr'))
31
- ->raw(";\n")
32
- ;
33
  }
34
  }
35
-
36
- class_alias('Twig_Node_Print', 'Twig\Node\PrintNode', false);
1
  <?php
2
 
3
+ use Twig\Node\PrintNode;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\PrintNode');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Print extends PrintNode
9
  {
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Sandbox.php CHANGED
@@ -1,44 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a sandbox node.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Node_Sandbox extends Twig_Node
18
- {
19
- public function __construct(Twig_NodeInterface $body, $lineno, $tag = null)
20
- {
21
- parent::__construct(['body' => $body], [], $lineno, $tag);
22
- }
23
 
24
- public function compile(Twig_Compiler $compiler)
 
25
  {
26
- $compiler
27
- ->addDebugInfo($this)
28
- ->write("\$sandbox = \$this->env->getExtension('Twig_Extension_Sandbox');\n")
29
- ->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n")
30
- ->indent()
31
- ->write("\$sandbox->enableSandbox();\n")
32
- ->outdent()
33
- ->write("}\n")
34
- ->subcompile($this->getNode('body'))
35
- ->write("if (!\$alreadySandboxed) {\n")
36
- ->indent()
37
- ->write("\$sandbox->disableSandbox();\n")
38
- ->outdent()
39
- ->write("}\n")
40
- ;
41
  }
42
  }
43
-
44
- class_alias('Twig_Node_Sandbox', 'Twig\Node\SandboxNode', false);
1
  <?php
2
 
3
+ use Twig\Node\SandboxNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\SandboxNode');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Sandbox extends SandboxNode
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/SandboxedPrint.php CHANGED
@@ -1,51 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Twig_Node_SandboxedPrint adds a check for the __toString() method
14
- * when the variable is an object and the sandbox is activated.
15
- *
16
- * When there is a simple Print statement, like {{ article }},
17
- * and if the sandbox is enabled, we need to check that the __toString()
18
- * method is allowed if 'article' is an object.
19
- *
20
- * @author Fabien Potencier <fabien@symfony.com>
21
- */
22
- class Twig_Node_SandboxedPrint extends Twig_Node_Print
23
- {
24
- public function compile(Twig_Compiler $compiler)
25
- {
26
- $compiler
27
- ->addDebugInfo($this)
28
- ->write('echo $this->env->getExtension(\'Twig_Extension_Sandbox\')->ensureToStringAllowed(')
29
- ->subcompile($this->getNode('expr'))
30
- ->raw(");\n")
31
- ;
32
- }
33
 
34
- /**
35
- * Removes node filters.
36
- *
37
- * This is mostly needed when another visitor adds filters (like the escaper one).
38
- *
39
- * @return Twig_Node
40
- */
41
- protected function removeNodeFilter(Twig_Node $node)
42
  {
43
- if ($node instanceof Twig_Node_Expression_Filter) {
44
- return $this->removeNodeFilter($node->getNode('node'));
45
- }
46
-
47
- return $node;
48
  }
49
  }
50
-
51
- class_alias('Twig_Node_SandboxedPrint', 'Twig\Node\SandboxedPrintNode', false);
1
  <?php
2
 
3
+ use Twig\Node\SandboxedPrintNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\SandboxedPrintNode');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_SandboxedPrint extends SandboxedPrintNode
 
 
 
 
 
 
9
  {
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Set.php CHANGED
@@ -1,98 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a set node.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface
18
- {
19
- public function __construct($capture, Twig_NodeInterface $names, Twig_NodeInterface $values, $lineno, $tag = null)
20
- {
21
- parent::__construct(['names' => $names, 'values' => $values], ['capture' => $capture, 'safe' => false], $lineno, $tag);
22
-
23
- /*
24
- * Optimizes the node when capture is used for a large block of text.
25
- *
26
- * {% set foo %}foo{% endset %} is compiled to $context['foo'] = new Twig_Markup("foo");
27
- */
28
- if ($this->getAttribute('capture')) {
29
- $this->setAttribute('safe', true);
30
-
31
- $values = $this->getNode('values');
32
- if ($values instanceof Twig_Node_Text) {
33
- $this->setNode('values', new Twig_Node_Expression_Constant($values->getAttribute('data'), $values->getTemplateLine()));
34
- $this->setAttribute('capture', false);
35
- }
36
- }
37
- }
38
 
39
- public function compile(Twig_Compiler $compiler)
 
40
  {
41
- $compiler->addDebugInfo($this);
42
-
43
- if (count($this->getNode('names')) > 1) {
44
- $compiler->write('list(');
45
- foreach ($this->getNode('names') as $idx => $node) {
46
- if ($idx) {
47
- $compiler->raw(', ');
48
- }
49
-
50
- $compiler->subcompile($node);
51
- }
52
- $compiler->raw(')');
53
- } else {
54
- if ($this->getAttribute('capture')) {
55
- $compiler
56
- ->write("ob_start();\n")
57
- ->subcompile($this->getNode('values'))
58
- ;
59
- }
60
-
61
- $compiler->subcompile($this->getNode('names'), false);
62
-
63
- if ($this->getAttribute('capture')) {
64
- $compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())");
65
- }
66
- }
67
-
68
- if (!$this->getAttribute('capture')) {
69
- $compiler->raw(' = ');
70
-
71
- if (count($this->getNode('names')) > 1) {
72
- $compiler->write('[');
73
- foreach ($this->getNode('values') as $idx => $value) {
74
- if ($idx) {
75
- $compiler->raw(', ');
76
- }
77
-
78
- $compiler->subcompile($value);
79
- }
80
- $compiler->raw(']');
81
- } else {
82
- if ($this->getAttribute('safe')) {
83
- $compiler
84
- ->raw("('' === \$tmp = ")
85
- ->subcompile($this->getNode('values'))
86
- ->raw(") ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())")
87
- ;
88
- } else {
89
- $compiler->subcompile($this->getNode('values'));
90
- }
91
- }
92
- }
93
-
94
- $compiler->raw(";\n");
95
  }
96
  }
97
-
98
- class_alias('Twig_Node_Set', 'Twig\Node\SetNode', false);
1
  <?php
2
 
3
+ use Twig\Node\SetNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\SetNode');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Set extends SetNode
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/SetTemp.php CHANGED
@@ -1,40 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * @internal
14
- */
15
- class Twig_Node_SetTemp extends Twig_Node
16
- {
17
- public function __construct($name, $lineno)
18
- {
19
- parent::__construct([], ['name' => $name], $lineno);
20
- }
21
 
22
- public function compile(Twig_Compiler $compiler)
 
23
  {
24
- $name = $this->getAttribute('name');
25
- $compiler
26
- ->addDebugInfo($this)
27
- ->write('if (isset($context[')
28
- ->string($name)
29
- ->raw('])) { $_')
30
- ->raw($name)
31
- ->raw('_ = $context[')
32
- ->repr($name)
33
- ->raw(']; } else { $_')
34
- ->raw($name)
35
- ->raw("_ = null; }\n")
36
- ;
37
  }
38
  }
39
-
40
- class_alias('Twig_Node_SetTemp', 'Twig\Node\SetTempNode', false);
1
  <?php
2
 
3
+ use Twig\Node\SetTempNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\SetTempNode');
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_SetTemp extends SetTempNode
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Spaceless.php CHANGED
@@ -1,37 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a spaceless node.
14
- *
15
- * It removes spaces between HTML tags.
16
- *
17
- * @author Fabien Potencier <fabien@symfony.com>
18
- */
19
- class Twig_Node_Spaceless extends Twig_Node
20
- {
21
- public function __construct(Twig_NodeInterface $body, $lineno, $tag = 'spaceless')
22
- {
23
- parent::__construct(['body' => $body], [], $lineno, $tag);
24
- }
25
 
26
- public function compile(Twig_Compiler $compiler)
 
27
  {
28
- $compiler
29
- ->addDebugInfo($this)
30
- ->write("ob_start();\n")
31
- ->subcompile($this->getNode('body'))
32
- ->write("echo trim(preg_replace('/>\s+</', '><', ob_get_clean()));\n")
33
- ;
34
  }
35
  }
36
-
37
- class_alias('Twig_Node_Spaceless', 'Twig\Node\SpacelessNode', false);
1
  <?php
2
 
3
+ use Twig\Node\SpacelessNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\SpacelessNode');
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Spaceless extends SpacelessNode
9
  {
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/Text.php CHANGED
@@ -1,36 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Represents a text node.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface
19
- {
20
- public function __construct($data, $lineno)
21
- {
22
- parent::__construct([], ['data' => $data], $lineno);
23
- }
24
 
25
- public function compile(Twig_Compiler $compiler)
 
26
  {
27
- $compiler
28
- ->addDebugInfo($this)
29
- ->write('echo ')
30
- ->string($this->getAttribute('data'))
31
- ->raw(";\n")
32
- ;
33
  }
34
  }
35
-
36
- class_alias('Twig_Node_Text', 'Twig\Node\TextNode', false);
1
  <?php
2
 
3
+ use Twig\Node\TextNode;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\TextNode');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_Text extends TextNode
9
  {
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Node/With.php CHANGED
@@ -1,64 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a nested "with" scope.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Node_With extends Twig_Node
18
- {
19
- public function __construct(Twig_Node $body, Twig_Node $variables = null, $only = false, $lineno, $tag = null)
20
- {
21
- $nodes = ['body' => $body];
22
- if (null !== $variables) {
23
- $nodes['variables'] = $variables;
24
- }
25
-
26
- parent::__construct($nodes, ['only' => (bool) $only], $lineno, $tag);
27
- }
28
 
29
- public function compile(Twig_Compiler $compiler)
 
30
  {
31
- $compiler->addDebugInfo($this);
32
-
33
- if ($this->hasNode('variables')) {
34
- $varsName = $compiler->getVarName();
35
- $compiler
36
- ->write(sprintf('$%s = ', $varsName))
37
- ->subcompile($this->getNode('variables'))
38
- ->raw(";\n")
39
- ->write(sprintf("if (!is_array(\$%s)) {\n", $varsName))
40
- ->indent()
41
- ->write("throw new Twig_Error_Runtime('Variables passed to the \"with\" tag must be a hash.');\n")
42
- ->outdent()
43
- ->write("}\n")
44
- ;
45
-
46
- if ($this->getAttribute('only')) {
47
- $compiler->write("\$context = ['_parent' => \$context];\n");
48
- } else {
49
- $compiler->write("\$context['_parent'] = \$context;\n");
50
- }
51
-
52
- $compiler->write(sprintf("\$context = array_merge(\$context, \$%s);\n", $varsName));
53
- } else {
54
- $compiler->write("\$context['_parent'] = \$context;\n");
55
- }
56
-
57
- $compiler
58
- ->subcompile($this->getNode('body'))
59
- ->write("\$context = \$context['_parent'];\n")
60
- ;
61
  }
62
  }
63
-
64
- class_alias('Twig_Node_With', 'Twig\Node\WithNode', false);
1
  <?php
2
 
3
+ use Twig\Node\WithNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\WithNode');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Node_With extends WithNode
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/NodeCaptureInterface.php CHANGED
@@ -1,21 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a node that captures any nested displayable nodes.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- interface Twig_NodeCaptureInterface
18
- {
19
- }
20
 
21
- class_alias('Twig_NodeCaptureInterface', 'Twig\Node\NodeCaptureInterface', false);
 
 
 
 
1
  <?php
2
 
3
+ use Twig\Node\NodeCaptureInterface;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\NodeCaptureInterface');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_NodeCaptureInterface extends NodeCaptureInterface
9
+ {
10
+ }
11
+ }
src/lib/vendor/twig/twig/lib/Twig/NodeInterface.php CHANGED
@@ -9,6 +9,8 @@
9
  * file that was distributed with this source code.
10
  */
11
 
 
 
12
  /**
13
  * Represents a node in the AST.
14
  *
@@ -16,12 +18,12 @@
16
  *
17
  * @deprecated since 1.12 (to be removed in 3.0)
18
  */
19
- interface Twig_NodeInterface extends Countable, IteratorAggregate
20
  {
21
  /**
22
  * Compiles the node to PHP.
23
  */
24
- public function compile(Twig_Compiler $compiler);
25
 
26
  /**
27
  * @deprecated since 1.27 (to be removed in 2.0)
9
  * file that was distributed with this source code.
10
  */
11
 
12
+ use Twig\Compiler;
13
+
14
  /**
15
  * Represents a node in the AST.
16
  *
18
  *
19
  * @deprecated since 1.12 (to be removed in 3.0)
20
  */
21
+ interface Twig_NodeInterface extends \Countable, \IteratorAggregate
22
  {
23
  /**
24
  * Compiles the node to PHP.
25
  */
26
+ public function compile(Compiler $compiler);
27
 
28
  /**
29
  * @deprecated since 1.27 (to be removed in 2.0)
src/lib/vendor/twig/twig/lib/Twig/NodeOutputInterface.php CHANGED
@@ -1,21 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a displayable node in the AST.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- interface Twig_NodeOutputInterface
18
- {
19
- }
20
 
21
- class_alias('Twig_NodeOutputInterface', 'Twig\Node\NodeOutputInterface', false);
 
 
 
 
1
  <?php
2
 
3
+ use Twig\Node\NodeOutputInterface;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Node\NodeOutputInterface');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_NodeOutputInterface extends NodeOutputInterface
9
+ {
10
+ }
11
+ }
src/lib/vendor/twig/twig/lib/Twig/NodeTraverser.php CHANGED
@@ -1,86 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Twig_NodeTraverser is a node traverser.
14
- *
15
- * It visits all nodes and their children and calls the given visitor for each.
16
- *
17
- * @final
18
- *
19
- * @author Fabien Potencier <fabien@symfony.com>
20
- */
21
- class Twig_NodeTraverser
22
- {
23
- protected $env;
24
- protected $visitors = [];
25
 
26
- /**
27
- * @param Twig_Environment $env
28
- * @param Twig_NodeVisitorInterface[] $visitors
29
- */
30
- public function __construct(Twig_Environment $env, array $visitors = [])
31
  {
32
- $this->env = $env;
33
- foreach ($visitors as $visitor) {
34
- $this->addVisitor($visitor);
35
- }
36
- }
37
-
38
- public function addVisitor(Twig_NodeVisitorInterface $visitor)
39
- {
40
- if (!isset($this->visitors[$visitor->getPriority()])) {
41
- $this->visitors[$visitor->getPriority()] = [];
42
- }
43
-
44
- $this->visitors[$visitor->getPriority()][] = $visitor;
45
- }
46
-
47
- /**
48
- * Traverses a node and calls the registered visitors.
49
- *
50
- * @return Twig_NodeInterface
51
- */
52
- public function traverse(Twig_NodeInterface $node)
53
- {
54
- ksort($this->visitors);
55
- foreach ($this->visitors as $visitors) {
56
- foreach ($visitors as $visitor) {
57
- $node = $this->traverseForVisitor($visitor, $node);
58
- }
59
- }
60
-
61
- return $node;
62
- }
63
-
64
- protected function traverseForVisitor(Twig_NodeVisitorInterface $visitor, Twig_NodeInterface $node = null)
65
- {
66
- if (null === $node) {
67
- return;
68
- }
69
-
70
- $node = $visitor->enterNode($node, $this->env);
71
-
72
- foreach ($node as $k => $n) {
73
- if (false !== $m = $this->traverseForVisitor($visitor, $n)) {
74
- if ($m !== $n) {
75
- $node->setNode($k, $m);
76
- }
77
- } else {
78
- $node->removeNode($k);
79
- }
80
- }
81
-
82
- return $visitor->leaveNode($node, $this->env);
83
  }
84
  }
85
-
86
- class_alias('Twig_NodeTraverser', 'Twig\NodeTraverser', false);
1
  <?php
2
 
3
+ use Twig\NodeTraverser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\NodeTraverser');
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_NodeTraverser extends NodeTraverser
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/NodeVisitor/Escaper.php CHANGED
@@ -1,154 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Twig_NodeVisitor_Escaper implements output escaping.
14
- *
15
- * @final
16
- *
17
- * @author Fabien Potencier <fabien@symfony.com>
18
- */
19
- class Twig_NodeVisitor_Escaper extends Twig_BaseNodeVisitor
20
- {
21
- protected $statusStack = [];
22
- protected $blocks = [];
23
- protected $safeAnalysis;
24
- protected $traverser;
25
- protected $defaultStrategy = false;
26
- protected $safeVars = [];
27
 
28
- public function __construct()
 
29
  {
30
- $this->safeAnalysis = new Twig_NodeVisitor_SafeAnalysis();
31
- }
32
-
33
- protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
34
- {
35
- if ($node instanceof Twig_Node_Module) {
36
- if ($env->hasExtension('Twig_Extension_Escaper') && $defaultStrategy = $env->getExtension('Twig_Extension_Escaper')->getDefaultStrategy($node->getTemplateName())) {
37
- $this->defaultStrategy = $defaultStrategy;
38
- }
39
- $this->safeVars = [];
40
- $this->blocks = [];
41
- } elseif ($node instanceof Twig_Node_AutoEscape) {
42
- $this->statusStack[] = $node->getAttribute('value');
43
- } elseif ($node instanceof Twig_Node_Block) {
44
- $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env);
45
- } elseif ($node instanceof Twig_Node_Import) {
46
- $this->safeVars[] = $node->getNode('var')->getAttribute('name');
47
- }
48
-
49
- return $node;
50
- }
51
-
52
- protected function doLeaveNode(Twig_Node $node, Twig_Environment $env)
53
- {
54
- if ($node instanceof Twig_Node_Module) {
55
- $this->defaultStrategy = false;
56
- $this->safeVars = [];
57
- $this->blocks = [];
58
- } elseif ($node instanceof Twig_Node_Expression_Filter) {
59
- return $this->preEscapeFilterNode($node, $env);
60
- } elseif ($node instanceof Twig_Node_Print) {
61
- return $this->escapePrintNode($node, $env, $this->needEscaping($env));
62
- }
63
-
64
- if ($node instanceof Twig_Node_AutoEscape || $node instanceof Twig_Node_Block) {
65
- array_pop($this->statusStack);
66
- } elseif ($node instanceof Twig_Node_BlockReference) {
67
- $this->blocks[$node->getAttribute('name')] = $this->needEscaping($env);
68
- }
69
-
70
- return $node;
71
- }
72
-
73
- protected function escapePrintNode(Twig_Node_Print $node, Twig_Environment $env, $type)
74
- {
75
- if (false === $type) {
76
- return $node;
77
- }
78
-
79
- $expression = $node->getNode('expr');
80
-
81
- if ($this->isSafeFor($type, $expression, $env)) {
82
- return $node;
83
- }
84
-
85
- $class = get_class($node);
86
-
87
- return new $class(
88
- $this->getEscaperFilter($type, $expression),
89
- $node->getTemplateLine()
90
- );
91
- }
92
-
93
- protected function preEscapeFilterNode(Twig_Node_Expression_Filter $filter, Twig_Environment $env)
94
- {
95
- $name = $filter->getNode('filter')->getAttribute('value');
96
-
97
- $type = $env->getFilter($name)->getPreEscape();
98
- if (null === $type) {
99
- return $filter;
100
- }
101
-
102
- $node = $filter->getNode('node');
103
- if ($this->isSafeFor($type, $node, $env)) {
104
- return $filter;
105
- }
106
-
107
- $filter->setNode('node', $this->getEscaperFilter($type, $node));
108
-
109
- return $filter;
110
- }
111
-
112
- protected function isSafeFor($type, Twig_NodeInterface $expression, $env)
113
- {
114
- $safe = $this->safeAnalysis->getSafe($expression);
115
-
116
- if (null === $safe) {
117
- if (null === $this->traverser) {
118
- $this->traverser = new Twig_NodeTraverser($env, [$this->safeAnalysis]);
119
- }
120
-
121
- $this->safeAnalysis->setSafeVars($this->safeVars);
122
-
123
- $this->traverser->traverse($expression);
124
- $safe = $this->safeAnalysis->getSafe($expression);
125
- }
126
-
127
- return in_array($type, $safe) || in_array('all', $safe);
128
- }
129
-
130
- protected function needEscaping(Twig_Environment $env)
131
- {
132
- if (count($this->statusStack)) {
133
- return $this->statusStack[count($this->statusStack) - 1];
134
- }
135
-
136
- return $this->defaultStrategy ? $this->defaultStrategy : false;
137
- }
138
-
139
- protected function getEscaperFilter($type, Twig_NodeInterface $node)
140
- {
141
- $line = $node->getTemplateLine();
142
- $name = new Twig_Node_Expression_Constant('escape', $line);
143
- $args = new Twig_Node([new Twig_Node_Expression_Constant((string) $type, $line), new Twig_Node_Expression_Constant(null, $line), new Twig_Node_Expression_Constant(true, $line)]);
144
-
145
- return new Twig_Node_Expression_Filter($node, $name, $args, $line);
146
- }
147
-
148
- public function getPriority()
149
- {
150
- return 0;
151
  }
152
  }
153
-
154
- class_alias('Twig_NodeVisitor_Escaper', 'Twig\NodeVisitor\EscaperNodeVisitor', false);
1
  <?php
2
 
3
+ use Twig\NodeVisitor\EscaperNodeVisitor;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\NodeVisitor\EscaperNodeVisitor');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_NodeVisitor_Escaper extends EscaperNodeVisitor
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php CHANGED
@@ -1,253 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Twig_NodeVisitor_Optimizer tries to optimizes the AST.
14
- *
15
- * This visitor is always the last registered one.
16
- *
17
- * You can configure which optimizations you want to activate via the
18
- * optimizer mode.
19
- *
20
- * @final
21
- *
22
- * @author Fabien Potencier <fabien@symfony.com>
23
- */
24
- class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
25
- {
26
- const OPTIMIZE_ALL = -1;
27
- const OPTIMIZE_NONE = 0;
28
- const OPTIMIZE_FOR = 2;
29
- const OPTIMIZE_RAW_FILTER = 4;
30
- const OPTIMIZE_VAR_ACCESS = 8;
31
 
32
- protected $loops = [];
33
- protected $loopsTargets = [];
34
- protected $optimizers;
35
- protected $prependedNodes = [];
36
- protected $inABody = false;
37
-
38
- /**
39
- * @param int $optimizers The optimizer mode
40
- */
41
- public function __construct($optimizers = -1)
42
- {
43
- if (!is_int($optimizers) || $optimizers > (self::OPTIMIZE_FOR | self::OPTIMIZE_RAW_FILTER | self::OPTIMIZE_VAR_ACCESS)) {
44
- throw new InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers));
45
- }
46
-
47
- $this->optimizers = $optimizers;
48
- }
49
-
50
- protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
51
- {
52
- if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
53
- $this->enterOptimizeFor($node, $env);
54
- }
55
-
56
- if (PHP_VERSION_ID < 50400 && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('Twig_Extension_Sandbox')) {
57
- if ($this->inABody) {
58
- if (!$node instanceof Twig_Node_Expression) {
59
- if ('Twig_Node' !== get_class($node)) {
60
- array_unshift($this->prependedNodes, []);
61
- }
62
- } else {
63
- $node = $this->optimizeVariables($node, $env);
64
- }
65
- } elseif ($node instanceof Twig_Node_Body) {
66
- $this->inABody = true;
67
- }
68
- }
69
-
70
- return $node;
71
- }
72
-
73
- protected function doLeaveNode(Twig_Node $node, Twig_Environment $env)
74
- {
75
- $expression = $node instanceof Twig_Node_Expression;
76
-
77
- if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
78
- $this->leaveOptimizeFor($node, $env);
79
- }
80
-
81
- if (self::OPTIMIZE_RAW_FILTER === (self::OPTIMIZE_RAW_FILTER & $this->optimizers)) {
82
- $node = $this->optimizeRawFilter($node, $env);
83
- }
84
-
85
- $node = $this->optimizePrintNode($node, $env);
86
-
87
- if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('Twig_Extension_Sandbox')) {
88
- if ($node instanceof Twig_Node_Body) {
89
- $this->inABody = false;
90
- } elseif ($this->inABody) {
91
- if (!$expression && 'Twig_Node' !== get_class($node) && $prependedNodes = array_shift($this->prependedNodes)) {
92
- $nodes = [];
93
- foreach (array_unique($prependedNodes) as $name) {
94
- $nodes[] = new Twig_Node_SetTemp($name, $node->getTemplateLine());
95
- }
96
-
97
- $nodes[] = $node;
98
- $node = new Twig_Node($nodes);
99
- }
100
- }
101
- }
102
-
103
- return $node;
104
- }
105
-
106
- protected function optimizeVariables(Twig_NodeInterface $node, Twig_Environment $env)
107
- {
108
- if ('Twig_Node_Expression_Name' === get_class($node) && $node->isSimple()) {
109
- $this->prependedNodes[0][] = $node->getAttribute('name');
110
-
111
- return new Twig_Node_Expression_TempName($node->getAttribute('name'), $node->getTemplateLine());
112
- }
113
-
114
- return $node;
115
- }
116
-
117
- /**
118
- * Optimizes print nodes.
119
- *
120
- * It replaces:
121
- *
122
- * * "echo $this->render(Parent)Block()" with "$this->display(Parent)Block()"
123
- *
124
- * @return Twig_NodeInterface
125
- */
126
- protected function optimizePrintNode(Twig_NodeInterface $node, Twig_Environment $env)
127
- {
128
- if (!$node instanceof Twig_Node_Print) {
129
- return $node;
130
- }
131
-
132
- $exprNode = $node->getNode('expr');
133
- if (
134
- $exprNode instanceof Twig_Node_Expression_BlockReference ||
135
- $exprNode instanceof Twig_Node_Expression_Parent
136
- ) {
137
- $exprNode->setAttribute('output', true);
138
-
139
- return $exprNode;
140
- }
141
-
142
- return $node;
143
- }
144
-
145
- /**
146
- * Removes "raw" filters.
147
- *
148
- * @return Twig_NodeInterface
149
- */
150
- protected function optimizeRawFilter(Twig_NodeInterface $node, Twig_Environment $env)
151
- {
152
- if ($node instanceof Twig_Node_Expression_Filter && 'raw' == $node->getNode('filter')->getAttribute('value')) {
153
- return $node->getNode('node');
154
- }
155
-
156
- return $node;
157
- }
158
-
159
- /**
160
- * Optimizes "for" tag by removing the "loop" variable creation whenever possible.
161
- */
162
- protected function enterOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env)
163
  {
164
- if ($node instanceof Twig_Node_For) {
165
- // disable the loop variable by default
166
- $node->setAttribute('with_loop', false);
167
- array_unshift($this->loops, $node);
168
- array_unshift($this->loopsTargets, $node->getNode('value_target')->getAttribute('name'));
169
- array_unshift($this->loopsTargets, $node->getNode('key_target')->getAttribute('name'));
170
- } elseif (!$this->loops) {
171
- // we are outside a loop
172
- return;
173
- }
174
-
175
- // when do we need to add the loop variable back?
176
-
177
- // the loop variable is referenced for the current loop
178
- elseif ($node instanceof Twig_Node_Expression_Name && 'loop' === $node->getAttribute('name')) {
179
- $node->setAttribute('always_defined', true);
180
- $this->addLoopToCurrent();
181
- }
182
-
183
- // optimize access to loop targets
184
- elseif ($node instanceof Twig_Node_Expression_Name && in_array($node->getAttribute('name'), $this->loopsTargets)) {
185
- $node->setAttribute('always_defined', true);
186
- }
187
-
188
- // block reference
189
- elseif ($node instanceof Twig_Node_BlockReference || $node instanceof Twig_Node_Expression_BlockReference) {
190
- $this->addLoopToCurrent();
191
- }
192
-
193
- // include without the only attribute
194
- elseif ($node instanceof Twig_Node_Include && !$node->getAttribute('only')) {
195
- $this->addLoopToAll();
196
- }
197
-
198
- // include function without the with_context=false parameter
199
- elseif ($node instanceof Twig_Node_Expression_Function
200
- && 'include' === $node->getAttribute('name')
201
- && (!$node->getNode('arguments')->hasNode('with_context')
202
- || false !== $node->getNode('arguments')->getNode('with_context')->getAttribute('value')
203
- )
204
- ) {
205
- $this->addLoopToAll();
206
- }
207
-
208
- // the loop variable is referenced via an attribute
209
- elseif ($node instanceof Twig_Node_Expression_GetAttr
210
- && (!$node->getNode('attribute') instanceof Twig_Node_Expression_Constant
211
- || 'parent' === $node->getNode('attribute')->getAttribute('value')
212
- )
213
- && (true === $this->loops[0]->getAttribute('with_loop')
214
- || ($node->getNode('node') instanceof Twig_Node_Expression_Name
215
- && 'loop' === $node->getNode('node')->getAttribute('name')
216
- )
217
- )
218
- ) {
219
- $this->addLoopToAll();
220
- }
221
- }
222
-
223
- /**
224
- * Optimizes "for" tag by removing the "loop" variable creation whenever possible.
225
- */
226
- protected function leaveOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env)
227
- {
228
- if ($node instanceof Twig_Node_For) {
229
- array_shift($this->loops);
230
- array_shift($this->loopsTargets);
231
- array_shift($this->loopsTargets);
232
- }
233
- }
234
-
235
- protected function addLoopToCurrent()
236
- {
237
- $this->loops[0]->setAttribute('with_loop', true);
238
- }
239
-
240
- protected function addLoopToAll()
241
- {
242
- foreach ($this->loops as $loop) {
243
- $loop->setAttribute('with_loop', true);
244
- }
245
- }
246
-
247
- public function getPriority()
248
- {
249
- return 255;
250
  }
251
  }
252
-
253
- class_alias('Twig_NodeVisitor_Optimizer', 'Twig\NodeVisitor\OptimizerNodeVisitor', false);
1
  <?php
2
 
3
+ use Twig\NodeVisitor\OptimizerNodeVisitor;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\NodeVisitor\OptimizerNodeVisitor');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_NodeVisitor_Optimizer extends OptimizerNodeVisitor
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php CHANGED
@@ -1,150 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * @final
14
- */
15
- class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor
16
- {
17
- protected $data = [];
18
- protected $safeVars = [];
19
 
20
- public function setSafeVars($safeVars)
 
21
  {
22
- $this->safeVars = $safeVars;
23
- }
24
-
25
- public function getSafe(Twig_NodeInterface $node)
26
- {
27
- $hash = spl_object_hash($node);
28
- if (!isset($this->data[$hash])) {
29
- return;
30
- }
31
-
32
- foreach ($this->data[$hash] as $bucket) {
33
- if ($bucket['key'] !== $node) {
34
- continue;
35
- }
36
-
37
- if (in_array('html_attr', $bucket['value'])) {
38
- $bucket['value'][] = 'html';
39
- }
40
-
41
- return $bucket['value'];
42
- }
43
- }
44
-
45
- protected function setSafe(Twig_NodeInterface $node, array $safe)
46
- {
47
- $hash = spl_object_hash($node);
48
- if (isset($this->data[$hash])) {
49
- foreach ($this->data[$hash] as &$bucket) {
50
- if ($bucket['key'] === $node) {
51
- $bucket['value'] = $safe;
52
-
53
- return;
54
- }
55
- }
56
- }
57
- $this->data[$hash][] = [
58
- 'key' => $node,
59
- 'value' => $safe,
60
- ];
61
- }
62
-
63
- protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
64
- {
65
- return $node;
66
- }
67
-
68
- protected function doLeaveNode(Twig_Node $node, Twig_Environment $env)
69
- {
70
- if ($node instanceof Twig_Node_Expression_Constant) {
71
- // constants are marked safe for all
72
- $this->setSafe($node, ['all']);
73
- } elseif ($node instanceof Twig_Node_Expression_BlockReference) {
74
- // blocks are safe by definition
75
- $this->setSafe($node, ['all']);
76
- } elseif ($node instanceof Twig_Node_Expression_Parent) {
77
- // parent block is safe by definition
78
- $this->setSafe($node, ['all']);
79
- } elseif ($node instanceof Twig_Node_Expression_Conditional) {
80
- // intersect safeness of both operands
81
- $safe = $this->intersectSafe($this->getSafe($node->getNode('expr2')), $this->getSafe($node->getNode('expr3')));
82
- $this->setSafe($node, $safe);
83
- } elseif ($node instanceof Twig_Node_Expression_Filter) {
84
- // filter expression is safe when the filter is safe
85
- $name = $node->getNode('filter')->getAttribute('value');
86
- $args = $node->getNode('arguments');
87
- if (false !== $filter = $env->getFilter($name)) {
88
- $safe = $filter->getSafe($args);
89
- if (null === $safe) {
90
- $safe = $this->intersectSafe($this->getSafe($node->getNode('node')), $filter->getPreservesSafety());
91
- }
92
- $this->setSafe($node, $safe);
93
- } else {
94
- $this->setSafe($node, []);
95
- }
96
- } elseif ($node instanceof Twig_Node_Expression_Function) {
97
- // function expression is safe when the function is safe
98
- $name = $node->getAttribute('name');
99
- $args = $node->getNode('arguments');
100
- $function = $env->getFunction($name);
101
- if (false !== $function) {
102
- $this->setSafe($node, $function->getSafe($args));
103
- } else {
104
- $this->setSafe($node, []);
105
- }
106
- } elseif ($node instanceof Twig_Node_Expression_MethodCall) {
107
- if ($node->getAttribute('safe')) {
108
- $this->setSafe($node, ['all']);
109
- } else {
110
- $this->setSafe($node, []);
111
- }
112
- } elseif ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name) {
113
- $name = $node->getNode('node')->getAttribute('name');
114
- // attributes on template instances are safe
115
- if ('_self' == $name || in_array($name, $this->safeVars)) {
116
- $this->setSafe($node, ['all']);
117
- } else {
118
- $this->setSafe($node, []);
119
- }
120
- } else {
121
- $this->setSafe($node, []);
122
- }
123
-
124
- return $node;
125
- }
126
-
127
- protected function intersectSafe(array $a = null, array $b = null)
128
- {
129
- if (null === $a || null === $b) {
130
- return [];
131
- }
132
-
133
- if (in_array('all', $a)) {
134
- return $b;
135
- }
136
-
137
- if (in_array('all', $b)) {
138
- return $a;
139
- }
140
-
141
- return array_intersect($a, $b);
142
- }
143
-
144
- public function getPriority()
145
- {
146
- return 0;
147
  }
148
  }
149
-
150
- class_alias('Twig_NodeVisitor_SafeAnalysis', 'Twig\NodeVisitor\SafeAnalysisNodeVisitor', false);
1
  <?php
2
 
3
+ use Twig\NodeVisitor\SafeAnalysisNodeVisitor;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\NodeVisitor\SafeAnalysisNodeVisitor');
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_NodeVisitor_SafeAnalysis extends SafeAnalysisNodeVisitor
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/NodeVisitor/Sandbox.php CHANGED
@@ -1,82 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Twig_NodeVisitor_Sandbox implements sandboxing.
14
- *
15
- * @final
16
- *
17
- * @author Fabien Potencier <fabien@symfony.com>
18
- */
19
- class Twig_NodeVisitor_Sandbox extends Twig_BaseNodeVisitor
20
- {
21
- protected $inAModule = false;
22
- protected $tags;
23
- protected $filters;
24
- protected $functions;
25
 
26
- protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
 
27
  {
28
- if ($node instanceof Twig_Node_Module) {
29
- $this->inAModule = true;
30
- $this->tags = [];
31
- $this->filters = [];
32
- $this->functions = [];
33
-
34
- return $node;
35
- } elseif ($this->inAModule) {
36
- // look for tags
37
- if ($node->getNodeTag() && !isset($this->tags[$node->getNodeTag()])) {
38
- $this->tags[$node->getNodeTag()] = $node;
39
- }
40
-
41
- // look for filters
42
- if ($node instanceof Twig_Node_Expression_Filter && !isset($this->filters[$node->getNode('filter')->getAttribute('value')])) {
43
- $this->filters[$node->getNode('filter')->getAttribute('value')] = $node;
44
- }
45
-
46
- // look for functions
47
- if ($node instanceof Twig_Node_Expression_Function && !isset($this->functions[$node->getAttribute('name')])) {
48
- $this->functions[$node->getAttribute('name')] = $node;
49
- }
50
-
51
- // the .. operator is equivalent to the range() function
52
- if ($node instanceof Twig_Node_Expression_Binary_Range && !isset($this->functions['range'])) {
53
- $this->functions['range'] = $node;
54
- }
55
-
56
- // wrap print to check __toString() calls
57
- if ($node instanceof Twig_Node_Print) {
58
- return new Twig_Node_SandboxedPrint($node->getNode('expr'), $node->getTemplateLine(), $node->getNodeTag());
59
- }
60
- }
61
-
62
- return $node;
63
- }
64
-
65
- protected function doLeaveNode(Twig_Node $node, Twig_Environment $env)
66
- {
67
- if ($node instanceof Twig_Node_Module) {
68
- $this->inAModule = false;
69
-
70
- $node->setNode('display_start', new Twig_Node([new Twig_Node_CheckSecurity($this->filters, $this->tags, $this->functions), $node->getNode('display_start')]));
71
- }
72
-
73
- return $node;
74
- }
75
-
76
- public function getPriority()
77
- {
78
- return 0;
79
  }
80
  }
81
-
82
- class_alias('Twig_NodeVisitor_Sandbox', 'Twig\NodeVisitor\SandboxNodeVisitor', false);
1
  <?php
2
 
3
+ use Twig\NodeVisitor\SandboxNodeVisitor;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\NodeVisitor\SandboxNodeVisitor');
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_NodeVisitor_Sandbox extends SandboxNodeVisitor
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/NodeVisitorInterface.php CHANGED
@@ -1,45 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Twig_NodeVisitorInterface is the interface the all node visitor classes must implement.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- interface Twig_NodeVisitorInterface
18
- {
19
- /**
20
- * Called before child nodes are visited.
21
- *
22
- * @return Twig_NodeInterface The modified node
23
- */
24
- public function enterNode(Twig_NodeInterface $node, Twig_Environment $env);
25
 
26
- /**
27
- * Called after child nodes are visited.
28
- *
29
- * @return Twig_NodeInterface|false The modified node or false if the node must be removed
30
- */
31
- public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env);
32
-
33
- /**
34
- * Returns the priority for this visitor.
35
- *
36
- * Priority should be between -10 and 10 (0 is the default).
37
- *
38
- * @return int The priority level
39
- */
40
- public function getPriority();
41
  }
42
-
43
- class_alias('Twig_NodeVisitorInterface', 'Twig\NodeVisitor\NodeVisitorInterface', false);
44
- class_exists('Twig_Environment');
45
- class_exists('Twig_Node');
1
  <?php
2
 
3
+ use Twig\NodeVisitor\NodeVisitorInterface;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\NodeVisitor\NodeVisitorInterface');
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_NodeVisitorInterface extends NodeVisitorInterface
9
+ {
10
+ }
 
 
 
 
 
 
 
 
 
 
 
11
  }
 
 
 
 
src/lib/vendor/twig/twig/lib/Twig/Parser.php CHANGED
@@ -1,416 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Default parser implementation.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- */
18
- class Twig_Parser implements Twig_ParserInterface
19
- {
20
- protected $stack = [];
21
- protected $stream;
22
- protected $parent;
23
- protected $handlers;
24
- protected $visitors;
25
- protected $expressionParser;
26
- protected $blocks;
27
- protected $blockStack;
28
- protected $macros;
29
- protected $env;
30
- protected $reservedMacroNames;
31
- protected $importedSymbols;
32
- protected $traits;
33
- protected $embeddedTemplates = [];
34
- private $varNameSalt = 0;
35
 
36
- public function __construct(Twig_Environment $env)
 
37
  {
38
- $this->env = $env;
39
- }
40
-
41
- /**
42
- * @deprecated since 1.27 (to be removed in 2.0)
43
- */
44
- public function getEnvironment()
45
- {
46
- @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0.', E_USER_DEPRECATED);
47
-
48
- return $this->env;
49
- }
50
-
51
- public function getVarName()
52
- {
53
- return sprintf('__internal_%s', hash('sha256', __METHOD__.$this->stream->getSourceContext()->getCode().$this->varNameSalt++));
54
- }
55
-
56
- /**
57
- * @deprecated since 1.27 (to be removed in 2.0). Use $parser->getStream()->getSourceContext()->getPath() instead.
58
- */
59
- public function getFilename()
60
- {
61
- @trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use $parser->getStream()->getSourceContext()->getPath() instead.', __METHOD__), E_USER_DEPRECATED);
62
-
63
- return $this->stream->getSourceContext()->getName();
64
- }
65
-
66
- public function parse(Twig_TokenStream $stream, $test = null, $dropNeedle = false)
67
- {
68
- // push all variables into the stack to keep the current state of the parser
69
- // using get_object_vars() instead of foreach would lead to https://bugs.php.net/71336
70
- // This hack can be removed when min version if PHP 7.0
71
- $vars = [];
72
- foreach ($this as $k => $v) {
73
- $vars[$k] = $v;
74
- }
75
-
76
- unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser'], $vars['reservedMacroNames']);
77
- $this->stack[] = $vars;
78
-
79
- // tag handlers
80
- if (null === $this->handlers) {
81
- $this->handlers = $this->env->getTokenParsers();
82
- $this->handlers->setParser($this);
83
- }
84
-
85
- // node visitors
86
- if (null === $this->visitors) {
87
- $this->visitors = $this->env->getNodeVisitors();
88
- }
89
-
90
- if (null === $this->expressionParser) {
91
- $this->expressionParser = new Twig_ExpressionParser($this, $this->env);
92
- }
93
-
94
- $this->stream = $stream;
95
- $this->parent = null;
96
- $this->blocks = [];
97
- $this->macros = [];
98
- $this->traits = [];
99
- $this->blockStack = [];
100
- $this->importedSymbols = [[]];
101
- $this->embeddedTemplates = [];
102
- $this->varNameSalt = 0;
103
-
104
- try {
105
- $body = $this->subparse($test, $dropNeedle);
106
-
107
- if (null !== $this->parent && null === $body = $this->filterBodyNodes($body)) {
108
- $body = new Twig_Node();
109
- }
110
- } catch (Twig_Error_Syntax $e) {
111
- if (!$e->getSourceContext()) {
112
- $e->setSourceContext($this->stream->getSourceContext());
113
- }
114
-
115
- if (!$e->getTemplateLine()) {
116
- $e->setTemplateLine($this->stream->getCurrent()->getLine());
117
- }
118
-
119
- throw $e;
120
- }
121
-
122
- $node = new Twig_Node_Module(new Twig_Node_Body([$body]), $this->parent, new Twig_Node($this->blocks), new Twig_Node($this->macros), new Twig_Node($this->traits), $this->embeddedTemplates, $stream->getSourceContext());
123
-
124
- $traverser = new Twig_NodeTraverser($this->env, $this->visitors);
125
-
126
- $node = $traverser->traverse($node);
127
-
128
- // restore previous stack so previous parse() call can resume working
129
- foreach (array_pop($this->stack) as $key => $val) {
130
- $this->$key = $val;
131
- }
132
-
133
- return $node;
134
- }
135
-
136
- public function subparse($test, $dropNeedle = false)
137
- {
138
- $lineno = $this->getCurrentToken()->getLine();
139
- $rv = [];
140
- while (!$this->stream->isEOF()) {
141
- switch ($this->getCurrentToken()->getType()) {
142
- case Twig_Token::TEXT_TYPE:
143
- $token = $this->stream->next();
144
- $rv[] = new Twig_Node_Text($token->getValue(), $token->getLine());
145
- break;
146
-
147
- case Twig_Token::VAR_START_TYPE:
148
- $token = $this->stream->next();
149
- $expr = $this->expressionParser->parseExpression();
150
- $this->stream->expect(Twig_Token::VAR_END_TYPE);
151
- $rv[] = new Twig_Node_Print($expr, $token->getLine());
152
- break;
153
-
154
- case Twig_Token::BLOCK_START_TYPE:
155
- $this->stream->next();
156
- $token = $this->getCurrentToken();
157
-
158
- if (Twig_Token::NAME_TYPE !== $token->getType()) {
159
- throw new Twig_Error_Syntax('A block must start with a tag name.', $token->getLine(), $this->stream->getSourceContext());
160
- }
161
-
162
- if (null !== $test && call_user_func($test, $token)) {
163
- if ($dropNeedle) {
164
- $this->stream->next();
165
- }
166
-
167
- if (1 === count($rv)) {
168
- return $rv[0];
169
- }
170
-
171
- return new Twig_Node($rv, [], $lineno);
172
- }
173
-
174
- $subparser = $this->handlers->getTokenParser($token->getValue());
175
- if (null === $subparser) {
176
- if (null !== $test) {
177
- $e = new Twig_Error_Syntax(sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->stream->getSourceContext());
178
-
179
- if (is_array($test) && isset($test[0]) && $test[0] instanceof Twig_TokenParserInterface) {
180
- $e->appendMessage(sprintf(' (expecting closing tag for the "%s" tag defined near line %s).', $test[0]->getTag(), $lineno));
181
- }
182
- } else {
183
- $e = new Twig_Error_Syntax(sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->stream->getSourceContext());
184
- $e->addSuggestions($token->getValue(), array_keys($this->env->getTags()));
185
- }
186
-
187
- throw $e;
188
- }
189
-
190
- $this->stream->next();
191
-
192
- $node = $subparser->parse($token);
193
- if (null !== $node) {
194
- $rv[] = $node;
195
- }
196
- break;
197
-
198
- default:
199
- throw new Twig_Error_Syntax('Lexer or parser ended up in unsupported state.', $this->getCurrentToken()->getLine(), $this->stream->getSourceContext());
200
- }
201
- }
202
-
203
- if (1 === count($rv)) {
204
- return $rv[0];
205
- }
206
-
207
- return new Twig_Node($rv, [], $lineno);
208
- }
209
-
210
- /**
211
- * @deprecated since 1.27 (to be removed in 2.0)
212
- */
213
- public function addHandler($name, $class)
214
- {
215
- @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0.', E_USER_DEPRECATED);
216
-
217
- $this->handlers[$name] = $class;
218
- }
219
-
220
- /**
221
- * @deprecated since 1.27 (to be removed in 2.0)
222
- */
223
- public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
224
- {
225
- @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0.', E_USER_DEPRECATED);
226
-
227
- $this->visitors[] = $visitor;
228
- }
229
-
230
- public function getBlockStack()
231
- {
232
- return $this->blockStack;
233
- }
234
-
235
- public function peekBlockStack()
236
- {
237
- return $this->blockStack[count($this->blockStack) - 1];
238
- }
239
-
240
- public function popBlockStack()
241
- {
242
- array_pop($this->blockStack);
243
- }
244
-
245
- public function pushBlockStack($name)
246
- {
247
- $this->blockStack[] = $name;
248
- }
249
-
250
- public function hasBlock($name)
251
- {
252
- return isset($this->blocks[$name]);
253
- }
254
-
255
- public function getBlock($name)
256
- {
257
- return $this->blocks[$name];
258
- }
259
-
260
- public function setBlock($name, Twig_Node_Block $value)
261
- {
262
- $this->blocks[$name] = new Twig_Node_Body([$value], [], $value->getTemplateLine());
263
- }
264
-
265
- public function hasMacro($name)
266
- {
267
- return isset($this->macros[$name]);
268
- }
269
-
270
- public function setMacro($name, Twig_Node_Macro $node)
271
- {
272
- if ($this->isReservedMacroName($name)) {
273
- throw new Twig_Error_Syntax(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword.', $name), $node->getTemplateLine(), $this->stream->getSourceContext());
274
- }
275
-
276
- $this->macros[$name] = $node;
277
- }
278
-
279
- public function isReservedMacroName($name)
280
- {
281
- if (null === $this->reservedMacroNames) {
282
- $this->reservedMacroNames = [];
283
- $r = new ReflectionClass($this->env->getBaseTemplateClass());
284
- foreach ($r->getMethods() as $method) {
285
- $methodName = strtolower($method->getName());
286
-
287
- if ('get' === substr($methodName, 0, 3) && isset($methodName[3])) {
288
- $this->reservedMacroNames[] = substr($methodName, 3);
289
- }
290
- }
291
- }
292
-
293
- return in_array(strtolower($name), $this->reservedMacroNames);
294
- }
295
-
296
- public function addTrait($trait)
297
- {
298
- $this->traits[] = $trait;
299
- }
300
-
301
- public function hasTraits()
302
- {
303
- return count($this->traits) > 0;
304
- }
305
-
306
- public function embedTemplate(Twig_Node_Module $template)
307
- {
308
- $template->setIndex(mt_rand());
309
-
310
- $this->embeddedTemplates[] = $template;
311
- }
312
-
313
- public function addImportedSymbol($type, $alias, $name = null, Twig_Node_Expression $node = null)
314
- {
315
- $this->importedSymbols[0][$type][$alias] = ['name' => $name, 'node' => $node];
316
- }
317
-
318
- public function getImportedSymbol($type, $alias)
319
- {
320
- foreach ($this->importedSymbols as $functions) {
321
- if (isset($functions[$type][$alias])) {
322
- return $functions[$type][$alias];
323
- }
324
- }
325
- }
326
-
327
- public function isMainScope()
328
- {
329
- return 1 === count($this->importedSymbols);
330
- }
331
-
332
- public function pushLocalScope()
333
- {
334
- array_unshift($this->importedSymbols, []);
335
- }
336
-
337
- public function popLocalScope()
338
- {
339
- array_shift($this->importedSymbols);
340
- }
341
-
342
- /**
343
- * @return Twig_ExpressionParser
344
- */
345
- public function getExpressionParser()
346
- {
347
- return $this->expressionParser;
348
- }
349
-
350
- public function getParent()
351
- {
352
- return $this->parent;
353
- }
354
-
355
- public function setParent($parent)
356
- {
357
- $this->parent = $parent;
358
- }
359
-
360
- /**
361
- * @return Twig_TokenStream
362
- */
363
- public function getStream()
364
- {
365
- return $this->stream;
366
- }
367
-
368
- /**
369
- * @return Twig_Token
370
- */
371
- public function getCurrentToken()
372
- {
373
- return $this->stream->getCurrent();
374
- }
375
-
376
- protected function filterBodyNodes(Twig_NodeInterface $node)
377
- {
378
- // check that the body does not contain non-empty output nodes
379
- if (
380
- ($node instanceof Twig_Node_Text && !ctype_space($node->getAttribute('data')))
381
- ||
382
- (!$node instanceof Twig_Node_Text && !$node instanceof Twig_Node_BlockReference && $node instanceof Twig_NodeOutputInterface)
383
- ) {
384
- if (false !== strpos((string) $node, chr(0xEF).chr(0xBB).chr(0xBF))) {
385
- $t = substr($node->getAttribute('data'), 3);
386
- if ('' === $t || ctype_space($t)) {
387
- // bypass empty nodes starting with a BOM
388
- return;
389
- }
390
- }
391
-
392
- throw new Twig_Error_Syntax('A template that extends another one cannot include content outside Twig blocks. Did you forget to put the content inside a {% block %} tag?', $node->getTemplateLine(), $this->stream->getSourceContext());
393
- }
394
-
395
- // bypass nodes that will "capture" the output
396
- if ($node instanceof Twig_NodeCaptureInterface) {
397
- return $node;
398
- }
399
-
400
- if ($node instanceof Twig_NodeOutputInterface) {
401
- return;
402
- }
403
-
404
- foreach ($node as $k => $n) {
405
- if (null !== $n && null === $this->filterBodyNodes($n)) {
406
- $node->removeNode($k);
407
- }
408
- }
409
-
410
- return $node;
411
  }
412
  }
413
-
414
- class_alias('Twig_Parser', 'Twig\Parser', false);
415
- class_exists('Twig_Node');
416
- class_exists('Twig_TokenStream');
1
  <?php
2
 
3
+ use Twig\Parser;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Parser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Parser extends Parser
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
 
 
src/lib/vendor/twig/twig/lib/Twig/ParserInterface.php CHANGED
@@ -9,6 +9,10 @@
9
  * file that was distributed with this source code.
10
  */
11
 
 
 
 
 
12
  /**
13
  * Interface implemented by parser classes.
14
  *
@@ -21,9 +25,9 @@ interface Twig_ParserInterface
21
  /**
22
  * Converts a token stream to a node tree.
23
  *
24
- * @return Twig_Node_Module
25
  *
26
- * @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong
27
  */
28
- public function parse(Twig_TokenStream $stream);
29
  }
9
  * file that was distributed with this source code.
10
  */
11
 
12
+ use Twig\Error\SyntaxError;
13
+ use Twig\Node\ModuleNode;
14
+ use Twig\TokenStream;
15
+
16
  /**
17
  * Interface implemented by parser classes.
18
  *
25
  /**
26
  * Converts a token stream to a node tree.
27
  *
28
+ * @return ModuleNode
29
  *
30
+ * @throws SyntaxError When the token stream is syntactically or semantically wrong
31
  */
32
+ public function parse(TokenStream $stream);
33
  }
src/lib/vendor/twig/twig/lib/Twig/Profiler/Dumper/Base.php CHANGED
@@ -1,62 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * @author Fabien Potencier <fabien@symfony.com>
14
- */
15
- abstract class Twig_Profiler_Dumper_Base
16
- {
17
- private $root;
18
 
19
- public function dump(Twig_Profiler_Profile $profile)
 
20
  {
21
- return $this->dumpProfile($profile);
22
- }
23
-
24
- abstract protected function formatTemplate(Twig_Profiler_Profile $profile, $prefix);
25
-
26
- abstract protected function formatNonTemplate(Twig_Profiler_Profile $profile, $prefix);
27
-
28
- abstract protected function formatTime(Twig_Profiler_Profile $profile, $percent);
29
-
30
- private function dumpProfile(Twig_Profiler_Profile $profile, $prefix = '', $sibling = false)
31
- {
32
- if ($profile->isRoot()) {
33
- $this->root = $profile->getDuration();
34
- $start = $profile->getName();
35
- } else {
36
- if ($profile->isTemplate()) {
37
- $start = $this->formatTemplate($profile, $prefix);
38
- } else {
39
- $start = $this->formatNonTemplate($profile, $prefix);
40
- }
41
- $prefix .= $sibling ? '│ ' : ' ';
42
- }
43
-
44
- $percent = $this->root ? $profile->getDuration() / $this->root * 100 : 0;
45
-
46
- if ($profile->getDuration() * 1000 < 1) {
47
- $str = $start."\n";
48
- } else {
49
- $str = sprintf("%s %s\n", $start, $this->formatTime($profile, $percent));
50
- }
51
-
52
- $nCount = count($profile->getProfiles());
53
- foreach ($profile as $i => $p) {
54
- $str .= $this->dumpProfile($p, $prefix, $i + 1 !== $nCount);
55
- }
56
-
57
- return $str;
58
  }
59
  }
60
-
61
- class_alias('Twig_Profiler_Dumper_Base', 'Twig\Profiler\Dumper\BaseDumper', false);
62
- class_exists('Twig_Profiler_Profile');
1
  <?php
2
 
3
+ use Twig\Profiler\Dumper\BaseDumper;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Profiler\Dumper\BaseDumper');
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Profiler_Dumper_Base extends BaseDumper
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
 
src/lib/vendor/twig/twig/lib/Twig/Profiler/Dumper/Blackfire.php CHANGED
@@ -1,72 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
-
12
- /**
13
- * @author Fabien Potencier <fabien@symfony.com>
14
- *
15
- * @final
16
- */
17
- class Twig_Profiler_Dumper_Blackfire
18
- {
19
- public function dump(Twig_Profiler_Profile $profile)
20
- {
21
- $data = [];
22
- $this->dumpProfile('main()', $profile, $data);
23
- $this->dumpChildren('main()', $profile, $data);
24
-
25
- $start = sprintf('%f', microtime(true));
26
- $str = <<<EOF
27
- file-format: BlackfireProbe
28
- cost-dimensions: wt mu pmu
29
- request-start: {$start}
30
 
 
31
 
32
- EOF;
33
-
34
- foreach ($data as $name => $values) {
35
- $str .= "{$name}//{$values['ct']} {$values['wt']} {$values['mu']} {$values['pmu']}\n";
36
- }
37
-
38
- return $str;
39
- }
40
-
41
- private function dumpChildren($parent, Twig_Profiler_Profile $profile, &$data)
42
  {
43
- foreach ($profile as $p) {
44
- if ($p->isTemplate()) {
45
- $name = $p->getTemplate();
46
- } else {
47
- $name = sprintf('%s::%s(%s)', $p->getTemplate(), $p->getType(), $p->getName());
48
- }
49
- $this->dumpProfile(sprintf('%s==>%s', $parent, $name), $p, $data);
50
- $this->dumpChildren($name, $p, $data);
51
- }
52
- }
53
-
54
- private function dumpProfile($edge, Twig_Profiler_Profile $profile, &$data)
55
- {
56
- if (isset($data[$edge])) {
57
- ++$data[$edge]['ct'];
58
- $data[$edge]['wt'] += floor($profile->getDuration() * 1000000);
59
- $data[$edge]['mu'] += $profile->getMemoryUsage();
60
- $data[$edge]['pmu'] += $profile->getPeakMemoryUsage();
61
- } else {
62
- $data[$edge] = [
63
- 'ct' => 1,
64
- 'wt' => floor($profile->getDuration() * 1000000),
65
- 'mu' => $profile->getMemoryUsage(),
66
- 'pmu' => $profile->getPeakMemoryUsage(),
67
- ];
68
- }
69
  }
70
  }
71
-
72
- class_alias('Twig_Profiler_Dumper_Blackfire', 'Twig\Profiler\Dumper\BlackfireDumper', false);
1
  <?php
2
 
3
+ use Twig\Profiler\Dumper\BlackfireDumper;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Profiler\Dumper\BlackfireDumper');
6
 
7
+ if (\false) {
8
+ class Twig_Profiler_Dumper_Blackfire extends BlackfireDumper
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Profiler/Dumper/Html.php CHANGED
@@ -1,47 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * @author Fabien Potencier <fabien@symfony.com>
14
- *
15
- * @final
16
- */
17
- class Twig_Profiler_Dumper_Html extends Twig_Profiler_Dumper_Base
18
- {
19
- private static $colors = [
20
- 'block' => '#dfd',
21
- 'macro' => '#ddf',
22
- 'template' => '#ffd',
23
- 'big' => '#d44',
24
- ];
25
 
26
- public function dump(Twig_Profiler_Profile $profile)
 
27
  {
28
- return '<pre>'.parent::dump($profile).'</pre>';
29
- }
30
-
31
- protected function formatTemplate(Twig_Profiler_Profile $profile, $prefix)
32
- {
33
- return sprintf('%s└ <span style="background-color: %s">%s</span>', $prefix, self::$colors['template'], $profile->getTemplate());
34
- }
35
-
36
- protected function formatNonTemplate(Twig_Profiler_Profile $profile, $prefix)
37
- {
38
- return sprintf('%s└ %s::%s(<span style="background-color: %s">%s</span>)', $prefix, $profile->getTemplate(), $profile->getType(), isset(self::$colors[$profile->getType()]) ? self::$colors[$profile->getType()] : 'auto', $profile->getName());
39
- }
40
-
41
- protected function formatTime(Twig_Profiler_Profile $profile, $percent)
42
- {
43
- return sprintf('<span style="color: %s">%.2fms/%.0f%%</span>', $percent > 20 ? self::$colors['big'] : 'auto', $profile->getDuration() * 1000, $percent);
44
  }
45
  }
46
-
47
- class_alias('Twig_Profiler_Dumper_Html', 'Twig\Profiler\Dumper\HtmlDumper', false);
1
  <?php
2
 
3
+ use Twig\Profiler\Dumper\HtmlDumper;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Profiler\Dumper\HtmlDumper');
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Profiler_Dumper_Html extends HtmlDumper
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Profiler/Dumper/Text.php CHANGED
@@ -1,35 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * @author Fabien Potencier <fabien@symfony.com>
14
- *
15
- * @final
16
- */
17
- class Twig_Profiler_Dumper_Text extends Twig_Profiler_Dumper_Base
18
- {
19
- protected function formatTemplate(Twig_Profiler_Profile $profile, $prefix)
20
- {
21
- return sprintf('%s└ %s', $prefix, $profile->getTemplate());
22
- }
23
-
24
- protected function formatNonTemplate(Twig_Profiler_Profile $profile, $prefix)
25
- {
26
- return sprintf('%s└ %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), $profile->getName());
27
- }
28
 
29
- protected function formatTime(Twig_Profiler_Profile $profile, $percent)
 
30
  {
31
- return sprintf('%.2fms/%.0f%%', $profile->getDuration() * 1000, $percent);
32
  }
33
  }
34
-
35
- class_alias('Twig_Profiler_Dumper_Text', 'Twig\Profiler\Dumper\TextDumper', false);
1
  <?php
2
 
3
+ use Twig\Profiler\Dumper\TextDumper;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Profiler\Dumper\TextDumper');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Profiler_Dumper_Text extends TextDumper
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Profiler/Node/EnterProfile.php CHANGED
@@ -1,39 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a profile enter node.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Profiler_Node_EnterProfile extends Twig_Node
18
- {
19
- public function __construct($extensionName, $type, $name, $varName)
20
- {
21
- parent::__construct([], ['extension_name' => $extensionName, 'name' => $name, 'type' => $type, 'var_name' => $varName]);
22
- }
23
 
24
- public function compile(Twig_Compiler $compiler)
 
25
  {
26
- $compiler
27
- ->write(sprintf('$%s = $this->env->getExtension(', $this->getAttribute('var_name')))
28
- ->repr($this->getAttribute('extension_name'))
29
- ->raw(");\n")
30
- ->write(sprintf('$%s->enter($%s = new Twig_Profiler_Profile($this->getTemplateName(), ', $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof'))
31
- ->repr($this->getAttribute('type'))
32
- ->raw(', ')
33
- ->repr($this->getAttribute('name'))
34
- ->raw("));\n\n")
35
- ;
36
  }
37
  }
38
-
39
- class_alias('Twig_Profiler_Node_EnterProfile', 'Twig\Profiler\Node\EnterProfileNode', false);
1
  <?php
2
 
3
+ use Twig\Profiler\Node\EnterProfileNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Profiler\Node\EnterProfileNode');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Profiler_Node_EnterProfile extends EnterProfileNode
9
  {
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Profiler/Node/LeaveProfile.php CHANGED
@@ -1,33 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a profile leave node.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Profiler_Node_LeaveProfile extends Twig_Node
18
- {
19
- public function __construct($varName)
20
- {
21
- parent::__construct([], ['var_name' => $varName]);
22
- }
23
 
24
- public function compile(Twig_Compiler $compiler)
 
25
  {
26
- $compiler
27
- ->write("\n")
28
- ->write(sprintf("\$%s->leave(\$%s);\n\n", $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof'))
29
- ;
30
  }
31
  }
32
-
33
- class_alias('Twig_Profiler_Node_LeaveProfile', 'Twig\Profiler\Node\LeaveProfileNode', false);
1
  <?php
2
 
3
+ use Twig\Profiler\Node\LeaveProfileNode;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Profiler\Node\LeaveProfileNode');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Profiler_Node_LeaveProfile extends LeaveProfileNode
9
  {
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php CHANGED
@@ -1,67 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * @author Fabien Potencier <fabien@symfony.com>
14
- *
15
- * @final
16
- */
17
- class Twig_Profiler_NodeVisitor_Profiler extends Twig_BaseNodeVisitor
18
- {
19
- private $extensionName;
20
 
21
- public function __construct($extensionName)
 
22
  {
23
- $this->extensionName = $extensionName;
24
- }
25
-
26
- protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
27
- {
28
- return $node;
29
- }
30
-
31
- protected function doLeaveNode(Twig_Node $node, Twig_Environment $env)
32
- {
33
- if ($node instanceof Twig_Node_Module) {
34
- $varName = $this->getVarName();
35
- $node->setNode('display_start', new Twig_Node([new Twig_Profiler_Node_EnterProfile($this->extensionName, Twig_Profiler_Profile::TEMPLATE, $node->getTemplateName(), $varName), $node->getNode('display_start')]));
36
- $node->setNode('display_end', new Twig_Node([new Twig_Profiler_Node_LeaveProfile($varName), $node->getNode('display_end')]));
37
- } elseif ($node instanceof Twig_Node_Block) {
38
- $varName = $this->getVarName();
39
- $node->setNode('body', new Twig_Node_Body([
40
- new Twig_Profiler_Node_EnterProfile($this->extensionName, Twig_Profiler_Profile::BLOCK, $node->getAttribute('name'), $varName),
41
- $node->getNode('body'),
42
- new Twig_Profiler_Node_LeaveProfile($varName),
43
- ]));
44
- } elseif ($node instanceof Twig_Node_Macro) {
45
- $varName = $this->getVarName();
46
- $node->setNode('body', new Twig_Node_Body([
47
- new Twig_Profiler_Node_EnterProfile($this->extensionName, Twig_Profiler_Profile::MACRO, $node->getAttribute('name'), $varName),
48
- $node->getNode('body'),
49
- new Twig_Profiler_Node_LeaveProfile($varName),
50
- ]));
51
- }
52
-
53
- return $node;
54
- }
55
-
56
- private function getVarName()
57
- {
58
- return sprintf('__internal_%s', hash('sha256', $this->extensionName));
59
- }
60
-
61
- public function getPriority()
62
- {
63
- return 0;
64
  }
65
  }
66
-
67
- class_alias('Twig_Profiler_NodeVisitor_Profiler', 'Twig\Profiler\NodeVisitor\ProfilerNodeVisitor', false);
1
  <?php
2
 
3
+ use Twig\Profiler\NodeVisitor\ProfilerNodeVisitor;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Profiler\NodeVisitor\ProfilerNodeVisitor');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Profiler_NodeVisitor_Profiler extends ProfilerNodeVisitor
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Profiler/Profile.php CHANGED
@@ -1,170 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * @author Fabien Potencier <fabien@symfony.com>
14
- *
15
- * @final
16
- */
17
- class Twig_Profiler_Profile implements IteratorAggregate, Serializable
18
- {
19
- const ROOT = 'ROOT';
20
- const BLOCK = 'block';
21
- const TEMPLATE = 'template';
22
- const MACRO = 'macro';
23
 
24
- private $template;
25
- private $name;
26
- private $type;
27
- private $starts = [];
28
- private $ends = [];
29
- private $profiles = [];
30
-
31
- public function __construct($template = 'main', $type = self::ROOT, $name = 'main')
32
- {
33
- $this->template = $template;
34
- $this->type = $type;
35
- $this->name = 0 === strpos($name, '__internal_') ? 'INTERNAL' : $name;
36
- $this->enter();
37
- }
38
-
39
- public function getTemplate()
40
- {
41
- return $this->template;
42
- }
43
-
44
- public function getType()
45
- {
46
- return $this->type;
47
- }
48
-
49
- public function getName()
50
- {
51
- return $this->name;
52
- }
53
-
54
- public function isRoot()
55
- {
56
- return self::ROOT === $this->type;
57
- }
58
-
59
- public function isTemplate()
60
- {
61
- return self::TEMPLATE === $this->type;
62
- }
63
-
64
- public function isBlock()
65
- {
66
- return self::BLOCK === $this->type;
67
- }
68
-
69
- public function isMacro()
70
- {
71
- return self::MACRO === $this->type;
72
- }
73
-
74
- public function getProfiles()
75
- {
76
- return $this->profiles;
77
- }
78
-
79
- public function addProfile(self $profile)
80
- {
81
- $this->profiles[] = $profile;
82
- }
83
-
84
- /**
85
- * Returns the duration in microseconds.
86
- *
87
- * @return int
88
- */
89
- public function getDuration()
90
- {
91
- if ($this->isRoot() && $this->profiles) {
92
- // for the root node with children, duration is the sum of all child durations
93
- $duration = 0;
94
- foreach ($this->profiles as $profile) {
95
- $duration += $profile->getDuration();
96
- }
97
-
98
- return $duration;
99
- }
100
-
101
- return isset($this->ends['wt']) && isset($this->starts['wt']) ? $this->ends['wt'] - $this->starts['wt'] : 0;
102
- }
103
-
104
- /**
105
- * Returns the memory usage in bytes.
106
- *
107
- * @return int
108
- */
109
- public function getMemoryUsage()
110
  {
111
- return isset($this->ends['mu']) && isset($this->starts['mu']) ? $this->ends['mu'] - $this->starts['mu'] : 0;
112
- }
113
-
114
- /**
115
- * Returns the peak memory usage in bytes.
116
- *
117
- * @return int
118
- */
119
- public function getPeakMemoryUsage()
120
- {
121
- return isset($this->ends['pmu']) && isset($this->starts['pmu']) ? $this->ends['pmu'] - $this->starts['pmu'] : 0;
122
- }
123
-
124
- /**
125
- * Starts the profiling.
126
- */
127
- public function enter()
128
- {
129
- $this->starts = [
130
- 'wt' => microtime(true),
131
- 'mu' => memory_get_usage(),
132
- 'pmu' => memory_get_peak_usage(),
133
- ];
134
- }
135
-
136
- /**
137
- * Stops the profiling.
138
- */
139
- public function leave()
140
- {
141
- $this->ends = [
142
- 'wt' => microtime(true),
143
- 'mu' => memory_get_usage(),
144
- 'pmu' => memory_get_peak_usage(),
145
- ];
146
- }
147
-
148
- public function reset()
149
- {
150
- $this->starts = $this->ends = $this->profiles = [];
151
- $this->enter();
152
- }
153
-
154
- public function getIterator()
155
- {
156
- return new ArrayIterator($this->profiles);
157
- }
158
-
159
- public function serialize()
160
- {
161
- return serialize([$this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles]);
162
- }
163
-
164
- public function unserialize($data)
165
- {
166
- list($this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles) = unserialize($data);
167
  }
168
  }
169
-
170
- class_alias('Twig_Profiler_Profile', 'Twig\Profiler\Profile', false);
1
  <?php
2
 
3
+ use Twig\Profiler\Profile;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Profiler\Profile');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Profiler_Profile extends Profile
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/RuntimeLoaderInterface.php CHANGED
@@ -1,29 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Creates runtime implementations for Twig elements (filters/functions/tests).
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- interface Twig_RuntimeLoaderInterface
18
- {
19
- /**
20
- * Creates the runtime implementation of a Twig element (filter/function/test).
21
- *
22
- * @param string $class A runtime class
23
- *
24
- * @return object|null The runtime instance or null if the loader does not know how to create the runtime for this class
25
- */
26
- public function load($class);
27
- }
28
 
29
- class_alias('Twig_RuntimeLoaderInterface', 'Twig\RuntimeLoader\RuntimeLoaderInterface', false);
 
 
 
 
1
  <?php
2
 
3
+ use Twig\RuntimeLoader\RuntimeLoaderInterface;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\RuntimeLoader\RuntimeLoaderInterface');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_RuntimeLoaderInterface extends RuntimeLoaderInterface
9
+ {
10
+ }
11
+ }
src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityError.php CHANGED
@@ -1,21 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Exception thrown when a security error occurs at runtime.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- class Twig_Sandbox_SecurityError extends Twig_Error
18
- {
19
- }
20
 
21
- class_alias('Twig_Sandbox_SecurityError', 'Twig\Sandbox\SecurityError', false);
 
 
 
 
1
  <?php
2
 
3
+ use Twig\Sandbox\SecurityError;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Sandbox\SecurityError');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Sandbox_SecurityError extends SecurityError
9
+ {
10
+ }
11
+ }
src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php CHANGED
@@ -1,33 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Exception thrown when a not allowed filter is used in a template.
14
- *
15
- * @author Martin Hasoň <martin.hason@gmail.com>
16
- */
17
- class Twig_Sandbox_SecurityNotAllowedFilterError extends Twig_Sandbox_SecurityError
18
- {
19
- private $filterName;
20
 
21
- public function __construct($message, $functionName, $lineno = -1, $filename = null, Exception $previous = null)
 
22
  {
23
- parent::__construct($message, $lineno, $filename, $previous);
24
- $this->filterName = $functionName;
25
- }
26
-
27
- public function getFilterName()
28
- {
29
- return $this->filterName;
30
  }
31
  }
32
-
33
- class_alias('Twig_Sandbox_SecurityNotAllowedFilterError', 'Twig\Sandbox\SecurityNotAllowedFilterError', false);
1
  <?php
2
 
3
+ use Twig\Sandbox\SecurityNotAllowedFilterError;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Sandbox\SecurityNotAllowedFilterError');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Sandbox_SecurityNotAllowedFilterError extends SecurityNotAllowedFilterError
9
  {
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php CHANGED
@@ -1,33 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Exception thrown when a not allowed function is used in a template.
14
- *
15
- * @author Martin Hasoň <martin.hason@gmail.com>
16
- */
17
- class Twig_Sandbox_SecurityNotAllowedFunctionError extends Twig_Sandbox_SecurityError
18
- {
19
- private $functionName;
20
 
21
- public function __construct($message, $functionName, $lineno = -1, $filename = null, Exception $previous = null)
 
22
  {
23
- parent::__construct($message, $lineno, $filename, $previous);
24
- $this->functionName = $functionName;
25
- }
26
-
27
- public function getFunctionName()
28
- {
29
- return $this->functionName;
30
  }
31
  }
32
-
33
- class_alias('Twig_Sandbox_SecurityNotAllowedFunctionError', 'Twig\Sandbox\SecurityNotAllowedFunctionError', false);
1
  <?php
2
 
3
+ use Twig\Sandbox\SecurityNotAllowedFunctionError;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Sandbox\SecurityNotAllowedFunctionError');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Sandbox_SecurityNotAllowedFunctionError extends SecurityNotAllowedFunctionError
9
  {
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedMethodError.php CHANGED
@@ -1,40 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Exception thrown when a not allowed class method is used in a template.
14
- *
15
- * @author Kit Burton-Senior <mail@kitbs.com>
16
- */
17
- class Twig_Sandbox_SecurityNotAllowedMethodError extends Twig_Sandbox_SecurityError
18
- {
19
- private $className;
20
- private $methodName;
21
 
22
- public function __construct($message, $className, $methodName, $lineno = -1, $filename = null, Exception $previous = null)
 
23
  {
24
- parent::__construct($message, $lineno, $filename, $previous);
25
- $this->className = $className;
26
- $this->methodName = $methodName;
27
- }
28
-
29
- public function getClassName()
30
- {
31
- return $this->className;
32
- }
33
-
34
- public function getMethodName()
35
- {
36
- return $this->methodName;
37
  }
38
  }
39
-
40
- class_alias('Twig_Sandbox_SecurityNotAllowedMethodError', 'Twig\Sandbox\SecurityNotAllowedMethodError', false);
1
  <?php
2
 
3
+ use Twig\Sandbox\SecurityNotAllowedMethodError;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Sandbox\SecurityNotAllowedMethodError');
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Sandbox_SecurityNotAllowedMethodError extends SecurityNotAllowedMethodError
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedPropertyError.php CHANGED
@@ -1,40 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Exception thrown when a not allowed class property is used in a template.
14
- *
15
- * @author Kit Burton-Senior <mail@kitbs.com>
16
- */
17
- class Twig_Sandbox_SecurityNotAllowedPropertyError extends Twig_Sandbox_SecurityError
18
- {
19
- private $className;
20
- private $propertyName;
21
 
22
- public function __construct($message, $className, $propertyName, $lineno = -1, $filename = null, Exception $previous = null)
 
23
  {
24
- parent::__construct($message, $lineno, $filename, $previous);
25
- $this->className = $className;
26
- $this->propertyName = $propertyName;
27
- }
28
-
29
- public function getClassName()
30
- {
31
- return $this->className;
32
- }
33
-
34
- public function getPropertyName()
35
- {
36
- return $this->propertyName;
37
  }
38
  }
39
-
40
- class_alias('Twig_Sandbox_SecurityNotAllowedPropertyError', 'Twig\Sandbox\SecurityNotAllowedPropertyError', false);
1
  <?php
2
 
3
+ use Twig\Sandbox\SecurityNotAllowedPropertyError;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Sandbox\SecurityNotAllowedPropertyError');
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Sandbox_SecurityNotAllowedPropertyError extends SecurityNotAllowedPropertyError
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php CHANGED
@@ -1,33 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Exception thrown when a not allowed tag is used in a template.
14
- *
15
- * @author Martin Hasoň <martin.hason@gmail.com>
16
- */
17
- class Twig_Sandbox_SecurityNotAllowedTagError extends Twig_Sandbox_SecurityError
18
- {
19
- private $tagName;
20
 
21
- public function __construct($message, $tagName, $lineno = -1, $filename = null, Exception $previous = null)
 
22
  {
23
- parent::__construct($message, $lineno, $filename, $previous);
24
- $this->tagName = $tagName;
25
- }
26
-
27
- public function getTagName()
28
- {
29
- return $this->tagName;
30
  }
31
  }
32
-
33
- class_alias('Twig_Sandbox_SecurityNotAllowedTagError', 'Twig\Sandbox\SecurityNotAllowedTagError', false);
1
  <?php
2
 
3
+ use Twig\Sandbox\SecurityNotAllowedTagError;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Sandbox\SecurityNotAllowedTagError');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Sandbox_SecurityNotAllowedTagError extends SecurityNotAllowedTagError
9
  {
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php CHANGED
@@ -1,125 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a security policy which need to be enforced when sandbox mode is enabled.
14
- *
15
- * @final
16
- *
17
- * @author Fabien Potencier <fabien@symfony.com>
18
- */
19
- class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterface
20
- {
21
- protected $allowedTags;
22
- protected $allowedFilters;
23
- protected $allowedMethods;
24
- protected $allowedProperties;
25
- protected $allowedFunctions;
26
 
27
- public function __construct(array $allowedTags = [], array $allowedFilters = [], array $allowedMethods = [], array $allowedProperties = [], array $allowedFunctions = [])
 
28
  {
29
- $this->allowedTags = $allowedTags;
30
- $this->allowedFilters = $allowedFilters;
31
- $this->setAllowedMethods($allowedMethods);
32
- $this->allowedProperties = $allowedProperties;
33
- $this->allowedFunctions = $allowedFunctions;
34
- }
35
-
36
- public function setAllowedTags(array $tags)
37
- {
38
- $this->allowedTags = $tags;
39
- }
40
-
41
- public function setAllowedFilters(array $filters)
42
- {
43
- $this->allowedFilters = $filters;
44
- }
45
-
46
- public function setAllowedMethods(array $methods)
47
- {
48
- $this->allowedMethods = [];
49
- foreach ($methods as $class => $m) {
50
- $this->allowedMethods[$class] = array_map('strtolower', is_array($m) ? $m : [$m]);
51
- }
52
- }
53
-
54
- public function setAllowedProperties(array $properties)
55
- {
56
- $this->allowedProperties = $properties;
57
- }
58
-
59
- public function setAllowedFunctions(array $functions)
60
- {
61
- $this->allowedFunctions = $functions;
62
- }
63
-
64
- public function checkSecurity($tags, $filters, $functions)
65
- {
66
- foreach ($tags as $tag) {
67
- if (!in_array($tag, $this->allowedTags)) {
68
- throw new Twig_Sandbox_SecurityNotAllowedTagError(sprintf('Tag "%s" is not allowed.', $tag), $tag);
69
- }
70
- }
71
-
72
- foreach ($filters as $filter) {
73
- if (!in_array($filter, $this->allowedFilters)) {
74
- throw new Twig_Sandbox_SecurityNotAllowedFilterError(sprintf('Filter "%s" is not allowed.', $filter), $filter);
75
- }
76
- }
77
-
78
- foreach ($functions as $function) {
79
- if (!in_array($function, $this->allowedFunctions)) {
80
- throw new Twig_Sandbox_SecurityNotAllowedFunctionError(sprintf('Function "%s" is not allowed.', $function), $function);
81
- }
82
- }
83
- }
84
-
85
- public function checkMethodAllowed($obj, $method)
86
- {
87
- if ($obj instanceof Twig_TemplateInterface || $obj instanceof Twig_Markup) {
88
- return true;
89
- }
90
-
91
- $allowed = false;
92
- $method = strtolower($method);
93
- foreach ($this->allowedMethods as $class => $methods) {
94
- if ($obj instanceof $class) {
95
- $allowed = in_array($method, $methods);
96
-
97
- break;
98
- }
99
- }
100
-
101
- if (!$allowed) {
102
- $class = get_class($obj);
103
- throw new Twig_Sandbox_SecurityNotAllowedMethodError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, $class), $class, $method);
104
- }
105
- }
106
-
107
- public function checkPropertyAllowed($obj, $property)
108
- {
109
- $allowed = false;
110
- foreach ($this->allowedProperties as $class => $properties) {
111
- if ($obj instanceof $class) {
112
- $allowed = in_array($property, is_array($properties) ? $properties : [$properties]);
113
-
114
- break;
115
- }
116
- }
117
-
118
- if (!$allowed) {
119
- $class = get_class($obj);
120
- throw new Twig_Sandbox_SecurityNotAllowedPropertyError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, $class), $class, $property);
121
- }
122
  }
123
  }
124
-
125
- class_alias('Twig_Sandbox_SecurityPolicy', 'Twig\Sandbox\SecurityPolicy', false);
1
  <?php
2
 
3
+ use Twig\Sandbox\SecurityPolicy;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Sandbox\SecurityPolicy');
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Sandbox_SecurityPolicy extends SecurityPolicy
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicyInterface.php CHANGED
@@ -1,26 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Interfaces that all security policy classes must implements.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- interface Twig_Sandbox_SecurityPolicyInterface
18
- {
19
- public function checkSecurity($tags, $filters, $functions);
20
 
21
- public function checkMethodAllowed($obj, $method);
22
-
23
- public function checkPropertyAllowed($obj, $method);
 
24
  }
25
-
26
- class_alias('Twig_Sandbox_SecurityPolicyInterface', 'Twig\Sandbox\SecurityPolicyInterface', false);
1
  <?php
2
 
3
+ use Twig\Sandbox\SecurityPolicyInterface;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Sandbox\SecurityPolicyInterface');
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Sandbox_SecurityPolicyInterface extends SecurityPolicyInterface
9
+ {
10
+ }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/SimpleFilter.php CHANGED
@@ -1,121 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a template filter.
14
- *
15
- * @final
16
- *
17
- * @author Fabien Potencier <fabien@symfony.com>
18
- */
19
- class Twig_SimpleFilter
20
- {
21
- protected $name;
22
- protected $callable;
23
- protected $options;
24
- protected $arguments = [];
25
 
26
- public function __construct($name, $callable, array $options = [])
 
27
  {
28
- $this->name = $name;
29
- $this->callable = $callable;
30
- $this->options = array_merge([
31
- 'needs_environment' => false,
32
- 'needs_context' => false,
33
- 'is_variadic' => false,
34
- 'is_safe' => null,
35
- 'is_safe_callback' => null,
36
- 'pre_escape' => null,
37
- 'preserves_safety' => null,
38
- 'node_class' => 'Twig_Node_Expression_Filter',
39
- 'deprecated' => false,
40
- 'alternative' => null,
41
- ], $options);
42
- }
43
-
44
- public function getName()
45
- {
46
- return $this->name;
47
- }
48
-
49
- public function getCallable()
50
- {
51
- return $this->callable;
52
- }
53
-
54
- public function getNodeClass()
55
- {
56
- return $this->options['node_class'];
57
- }
58
-
59
- public function setArguments($arguments)
60
- {
61
- $this->arguments = $arguments;
62
- }
63
-
64
- public function getArguments()
65
- {
66
- return $this->arguments;
67
- }
68
-
69
- public function needsEnvironment()
70
- {
71
- return $this->options['needs_environment'];
72
- }
73
-
74
- public function needsContext()
75
- {
76
- return $this->options['needs_context'];
77
- }
78
-
79
- public function getSafe(Twig_Node $filterArgs)
80
- {
81
- if (null !== $this->options['is_safe']) {
82
- return $this->options['is_safe'];
83
- }
84
-
85
- if (null !== $this->options['is_safe_callback']) {
86
- return call_user_func($this->options['is_safe_callback'], $filterArgs);
87
- }
88
- }
89
-
90
- public function getPreservesSafety()
91
- {
92
- return $this->options['preserves_safety'];
93
- }
94
-
95
- public function getPreEscape()
96
- {
97
- return $this->options['pre_escape'];
98
- }
99
-
100
- public function isVariadic()
101
- {
102
- return $this->options['is_variadic'];
103
- }
104
-
105
- public function isDeprecated()
106
- {
107
- return (bool) $this->options['deprecated'];
108
- }
109
-
110
- public function getDeprecatedVersion()
111
- {
112
- return $this->options['deprecated'];
113
- }
114
-
115
- public function getAlternative()
116
- {
117
- return $this->options['alternative'];
118
  }
119
  }
120
-
121
- class_alias('Twig_SimpleFilter', 'Twig\TwigFilter', false);
1
  <?php
2
 
3
+ use Twig\TwigFilter;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TwigFilter');
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_SimpleFilter extends TwigFilter
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/SimpleFunction.php CHANGED
@@ -1,111 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a template function.
14
- *
15
- * @final
16
- *
17
- * @author Fabien Potencier <fabien@symfony.com>
18
- */
19
- class Twig_SimpleFunction
20
- {
21
- protected $name;
22
- protected $callable;
23
- protected $options;
24
- protected $arguments = [];
25
 
26
- public function __construct($name, $callable, array $options = [])
 
27
  {
28
- $this->name = $name;
29
- $this->callable = $callable;
30
- $this->options = array_merge([
31
- 'needs_environment' => false,
32
- 'needs_context' => false,
33
- 'is_variadic' => false,
34
- 'is_safe' => null,
35
- 'is_safe_callback' => null,
36
- 'node_class' => 'Twig_Node_Expression_Function',
37
- 'deprecated' => false,
38
- 'alternative' => null,
39
- ], $options);
40
- }
41
-
42
- public function getName()
43
- {
44
- return $this->name;
45
- }
46
-
47
- public function getCallable()
48
- {
49
- return $this->callable;
50
- }
51
-
52
- public function getNodeClass()
53
- {
54
- return $this->options['node_class'];
55
- }
56
-
57
- public function setArguments($arguments)
58
- {
59
- $this->arguments = $arguments;
60
- }
61
-
62
- public function getArguments()
63
- {
64
- return $this->arguments;
65
- }
66
-
67
- public function needsEnvironment()
68
- {
69
- return $this->options['needs_environment'];
70
- }
71
-
72
- public function needsContext()
73
- {
74
- return $this->options['needs_context'];
75
- }
76
-
77
- public function getSafe(Twig_Node $functionArgs)
78
- {
79
- if (null !== $this->options['is_safe']) {
80
- return $this->options['is_safe'];
81
- }
82
-
83
- if (null !== $this->options['is_safe_callback']) {
84
- return call_user_func($this->options['is_safe_callback'], $functionArgs);
85
- }
86
-
87
- return [];
88
- }
89
-
90
- public function isVariadic()
91
- {
92
- return $this->options['is_variadic'];
93
- }
94
-
95
- public function isDeprecated()
96
- {
97
- return (bool) $this->options['deprecated'];
98
- }
99
-
100
- public function getDeprecatedVersion()
101
- {
102
- return $this->options['deprecated'];
103
- }
104
-
105
- public function getAlternative()
106
- {
107
- return $this->options['alternative'];
108
  }
109
  }
110
-
111
- class_alias('Twig_SimpleFunction', 'Twig\TwigFunction', false);
1
  <?php
2
 
3
+ use Twig\TwigFunction;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TwigFunction');
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_SimpleFunction extends TwigFunction
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/SimpleTest.php CHANGED
@@ -1,85 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Represents a template test.
14
- *
15
- * @final
16
- *
17
- * @author Fabien Potencier <fabien@symfony.com>
18
- */
19
- class Twig_SimpleTest
20
- {
21
- protected $name;
22
- protected $callable;
23
- protected $options;
24
 
25
- private $arguments = [];
26
-
27
- public function __construct($name, $callable, array $options = [])
28
- {
29
- $this->name = $name;
30
- $this->callable = $callable;
31
- $this->options = array_merge([
32
- 'is_variadic' => false,
33
- 'node_class' => 'Twig_Node_Expression_Test',
34
- 'deprecated' => false,
35
- 'alternative' => null,
36
- ], $options);
37
- }
38
-
39
- public function getName()
40
  {
41
- return $this->name;
42
- }
43
-
44
- public function getCallable()
45
- {
46
- return $this->callable;
47
- }
48
-
49
- public function getNodeClass()
50
- {
51
- return $this->options['node_class'];
52
- }
53
-
54
- public function isVariadic()
55
- {
56
- return $this->options['is_variadic'];
57
- }
58
-
59
- public function isDeprecated()
60
- {
61
- return (bool) $this->options['deprecated'];
62
- }
63
-
64
- public function getDeprecatedVersion()
65
- {
66
- return $this->options['deprecated'];
67
- }
68
-
69
- public function getAlternative()
70
- {
71
- return $this->options['alternative'];
72
- }
73
-
74
- public function setArguments($arguments)
75
- {
76
- $this->arguments = $arguments;
77
- }
78
-
79
- public function getArguments()
80
- {
81
- return $this->arguments;
82
  }
83
  }
84
-
85
- class_alias('Twig_SimpleTest', 'Twig\TwigTest', false);
1
  <?php
2
 
3
+ use Twig\TwigTest;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TwigTest');
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_SimpleTest extends TwigTest
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Source.php CHANGED
@@ -1,53 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Holds information about a non-compiled Twig template.
14
- *
15
- * @final
16
- *
17
- * @author Fabien Potencier <fabien@symfony.com>
18
- */
19
- class Twig_Source
20
- {
21
- private $code;
22
- private $name;
23
- private $path;
24
 
25
- /**
26
- * @param string $code The template source code
27
- * @param string $name The template logical name
28
- * @param string $path The filesystem path of the template if any
29
- */
30
- public function __construct($code, $name, $path = '')
31
  {
32
- $this->code = $code;
33
- $this->name = $name;
34
- $this->path = $path;
35
- }
36
-
37
- public function getCode()
38
- {
39
- return $this->code;
40
- }
41
-
42
- public function getName()
43
- {
44
- return $this->name;
45
- }
46
-
47
- public function getPath()
48
- {
49
- return $this->path;
50
  }
51
  }
52
-
53
- class_alias('Twig_Source', 'Twig\Source', false);
1
  <?php
2
 
3
+ use Twig\Source;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Source');
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Source extends Source
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/SourceContextLoaderInterface.php CHANGED
@@ -1,33 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Adds a getSourceContext() method for loaders.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- *
17
- * @deprecated since 1.27 (to be removed in 3.0)
18
- */
19
- interface Twig_SourceContextLoaderInterface
20
- {
21
- /**
22
- * Returns the source context for a given template logical name.
23
- *
24
- * @param string $name The template logical name
25
- *
26
- * @return Twig_Source
27
- *
28
- * @throws Twig_Error_Loader When $name is not found
29
- */
30
- public function getSourceContext($name);
31
- }
32
 
33
- class_alias('Twig_SourceContextLoaderInterface', 'Twig\Loader\SourceContextLoaderInterface', false);
 
 
 
 
1
  <?php
2
 
3
+ use Twig\Loader\SourceContextLoaderInterface;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Loader\SourceContextLoaderInterface');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_SourceContextLoaderInterface extends SourceContextLoaderInterface
9
+ {
10
+ }
11
+ }
src/lib/vendor/twig/twig/lib/Twig/Template.php CHANGED
@@ -1,704 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Default base class for compiled templates.
15
- *
16
- * This class is an implementation detail of how template compilation currently
17
- * works, which might change. It should never be used directly. Use $twig->load()
18
- * instead, which returns an instance of Twig_TemplateWrapper.
19
- *
20
- * @author Fabien Potencier <fabien@symfony.com>
21
- *
22
- * @internal
23
- */
24
- abstract class Twig_Template implements Twig_TemplateInterface
25
- {
26
- /**
27
- * @internal
28
- */
29
- protected static $cache = [];
30
 
31
- protected $parent;
32
- protected $parents = [];
33
- protected $env;
34
- protected $blocks = [];
35
- protected $traits = [];
36
-
37
- public function __construct(Twig_Environment $env)
38
- {
39
- $this->env = $env;
40
- }
41
-
42
- /**
43
- * @internal this method will be removed in 2.0 and is only used internally to provide an upgrade path from 1.x to 2.0
44
- */
45
- public function __toString()
46
- {
47
- return $this->getTemplateName();
48
- }
49
-
50
- /**
51
- * Returns the template name.
52
- *
53
- * @return string The template name
54
- */
55
- abstract public function getTemplateName();
56
-
57
- /**
58
- * Returns debug information about the template.
59
- *
60
- * @return array Debug information
61
- *
62
- * @internal
63
- */
64
- public function getDebugInfo()
65
- {
66
- return [];
67
- }
68
-
69
- /**
70
- * Returns the template source code.
71
- *
72
- * @return string The template source code
73
- *
74
- * @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead
75
- */
76
- public function getSource()
77
- {
78
- @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED);
79
-
80
- return '';
81
- }
82
-
83
- /**
84
- * Returns information about the original template source code.
85
- *
86
- * @return Twig_Source
87
- */
88
- public function getSourceContext()
89
- {
90
- return new Twig_Source('', $this->getTemplateName());
91
- }
92
-
93
- /**
94
- * @deprecated since 1.20 (to be removed in 2.0)
95
- */
96
- public function getEnvironment()
97
- {
98
- @trigger_error('The '.__METHOD__.' method is deprecated since version 1.20 and will be removed in 2.0.', E_USER_DEPRECATED);
99
-
100
- return $this->env;
101
- }
102
-
103
- /**
104
- * Returns the parent template.
105
- *
106
- * This method is for internal use only and should never be called
107
- * directly.
108
- *
109
- * @param array $context
110
- *
111
- * @return Twig_TemplateInterface|Twig_TemplateWrapper|false The parent template or false if there is no parent
112
- *
113
- * @internal
114
- */
115
- public function getParent(array $context)
116
- {
117
- if (null !== $this->parent) {
118
- return $this->parent;
119
- }
120
-
121
- try {
122
- $parent = $this->doGetParent($context);
123
-
124
- if (false === $parent) {
125
- return false;
126
- }
127
-
128
- if ($parent instanceof self || $parent instanceof Twig_TemplateWrapper) {
129
- return $this->parents[$parent->getSourceContext()->getName()] = $parent;
130
- }
131
-
132
- if (!isset($this->parents[$parent])) {
133
- $this->parents[$parent] = $this->loadTemplate($parent);
134
- }
135
- } catch (Twig_Error_Loader $e) {
136
- $e->setSourceContext(null);
137
- $e->guess();
138
-
139
- throw $e;
140
- }
141
-
142
- return $this->parents[$parent];
143
- }
144
-
145
- protected function doGetParent(array $context)
146
- {
147
- return false;
148
- }
149
-
150
- public function isTraitable()
151
  {
152
- return true;
153
- }
154
-
155
- /**
156
- * Displays a parent block.
157
- *
158
- * This method is for internal use only and should never be called
159
- * directly.
160
- *
161
- * @param string $name The block name to display from the parent
162
- * @param array $context The context
163
- * @param array $blocks The current set of blocks
164
- *
165
- * @internal
166
- */
167
- public function displayParentBlock($name, array $context, array $blocks = [])
168
- {
169
- $name = (string) $name;
170
-
171
- if (isset($this->traits[$name])) {
172
- $this->traits[$name][0]->displayBlock($name, $context, $blocks, false);
173
- } elseif (false !== $parent = $this->getParent($context)) {
174
- $parent->displayBlock($name, $context, $blocks, false);
175
- } else {
176
- throw new Twig_Error_Runtime(sprintf('The template has no parent and no traits defining the "%s" block.', $name), -1, $this->getSourceContext());
177
- }
178
- }
179
-
180
- /**
181
- * Displays a block.
182
- *
183
- * This method is for internal use only and should never be called
184
- * directly.
185
- *
186
- * @param string $name The block name to display
187
- * @param array $context The context
188
- * @param array $blocks The current set of blocks
189
- * @param bool $useBlocks Whether to use the current set of blocks
190
- *
191
- * @internal
192
- */
193
- public function displayBlock($name, array $context, array $blocks = [], $useBlocks = true)
194
- {
195
- $name = (string) $name;
196
-
197
- if ($useBlocks && isset($blocks[$name])) {
198
- $template = $blocks[$name][0];
199
- $block = $blocks[$name][1];
200
- } elseif (isset($this->blocks[$name])) {
201
- $template = $this->blocks[$name][0];
202
- $block = $this->blocks[$name][1];
203
- } else {
204
- $template = null;
205
- $block = null;
206
- }
207
-
208
- // avoid RCEs when sandbox is enabled
209
- if (null !== $template && !$template instanceof self) {
210
- throw new LogicException('A block must be a method on a Twig_Template instance.');
211
- }
212
-
213
- if (null !== $template) {
214
- try {
215
- $template->$block($context, $blocks);
216
- } catch (Twig_Error $e) {
217
- if (!$e->getSourceContext()) {
218
- $e->setSourceContext($template->getSourceContext());
219
- }
220
-
221
- // this is mostly useful for Twig_Error_Loader exceptions
222
- // see Twig_Error_Loader
223
- if (false === $e->getTemplateLine()) {
224
- $e->setTemplateLine(-1);
225
- $e->guess();
226
- }
227
-
228
- throw $e;
229
- } catch (Exception $e) {
230
- throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getSourceContext(), $e);
231
- }
232
- } elseif (false !== $parent = $this->getParent($context)) {
233
- $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks), false);
234
- } else {
235
- @trigger_error(sprintf('Silent display of undefined block "%s" in template "%s" is deprecated since version 1.29 and will throw an exception in 2.0. Use the "block(\'%s\') is defined" expression to test for block existence.', $name, $this->getTemplateName(), $name), E_USER_DEPRECATED);
236
- }
237
- }
238
-
239
- /**
240
- * Renders a parent block.
241
- *
242
- * This method is for internal use only and should never be called
243
- * directly.
244
- *
245
- * @param string $name The block name to render from the parent
246
- * @param array $context The context
247
- * @param array $blocks The current set of blocks
248
- *
249
- * @return string The rendered block
250
- *
251
- * @internal
252
- */
253
- public function renderParentBlock($name, array $context, array $blocks = [])
254
- {
255
- ob_start();
256
- $this->displayParentBlock($name, $context, $blocks);
257
-
258
- return ob_get_clean();
259
- }
260
-
261
- /**
262
- * Renders a block.
263
- *
264
- * This method is for internal use only and should never be called
265
- * directly.
266
- *
267
- * @param string $name The block name to render
268
- * @param array $context The context
269
- * @param array $blocks The current set of blocks
270
- * @param bool $useBlocks Whether to use the current set of blocks
271
- *
272
- * @return string The rendered block
273
- *
274
- * @internal
275
- */
276
- public function renderBlock($name, array $context, array $blocks = [], $useBlocks = true)
277
- {
278
- ob_start();
279
- $this->displayBlock($name, $context, $blocks, $useBlocks);
280
-
281
- return ob_get_clean();
282
- }
283
-
284
- /**
285
- * Returns whether a block exists or not in the current context of the template.
286
- *
287
- * This method checks blocks defined in the current template
288
- * or defined in "used" traits or defined in parent templates.
289
- *
290
- * @param string $name The block name
291
- * @param array $context The context
292
- * @param array $blocks The current set of blocks
293
- *
294
- * @return bool true if the block exists, false otherwise
295
- *
296
- * @internal
297
- */
298
- public function hasBlock($name, array $context = null, array $blocks = [])
299
- {
300
- if (null === $context) {
301
- @trigger_error('The '.__METHOD__.' method is internal and should never be called; calling it directly is deprecated since version 1.28 and won\'t be possible anymore in 2.0.', E_USER_DEPRECATED);
302
-
303
- return isset($this->blocks[(string) $name]);
304
- }
305
-
306
- if (isset($blocks[$name])) {
307
- return $blocks[$name][0] instanceof self;
308
- }
309
-
310
- if (isset($this->blocks[$name])) {
311
- return true;
312
- }
313
-
314
- if (false !== $parent = $this->getParent($context)) {
315
- return $parent->hasBlock($name, $context);
316
- }
317
-
318
- return false;
319
- }
320
-
321
- /**
322
- * Returns all block names in the current context of the template.
323
- *
324
- * This method checks blocks defined in the current template
325
- * or defined in "used" traits or defined in parent templates.
326
- *
327
- * @param array $context The context
328
- * @param array $blocks The current set of blocks
329
- *
330
- * @return array An array of block names
331
- *
332
- * @internal
333
- */
334
- public function getBlockNames(array $context = null, array $blocks = [])
335
- {
336
- if (null === $context) {
337
- @trigger_error('The '.__METHOD__.' method is internal and should never be called; calling it directly is deprecated since version 1.28 and won\'t be possible anymore in 2.0.', E_USER_DEPRECATED);
338
-
339
- return array_keys($this->blocks);
340
- }
341
-
342
- $names = array_merge(array_keys($blocks), array_keys($this->blocks));
343
-
344
- if (false !== $parent = $this->getParent($context)) {
345
- $names = array_merge($names, $parent->getBlockNames($context));
346
- }
347
-
348
- return array_unique($names);
349
- }
350
-
351
- protected function loadTemplate($template, $templateName = null, $line = null, $index = null)
352
- {
353
- try {
354
- if (is_array($template)) {
355
- return $this->env->resolveTemplate($template);
356
- }
357
-
358
- if ($template instanceof self || $template instanceof Twig_TemplateWrapper) {
359
- return $template;
360
- }
361
-
362
- return $this->env->loadTemplate($template, $index);
363
- } catch (Twig_Error $e) {
364
- if (!$e->getSourceContext()) {
365
- $e->setSourceContext($templateName ? new Twig_Source('', $templateName) : $this->getSourceContext());
366
- }
367
-
368
- if ($e->getTemplateLine()) {
369
- throw $e;
370
- }
371
-
372
- if (!$line) {
373
- $e->guess();
374
- } else {
375
- $e->setTemplateLine($line);
376
- }
377
-
378
- throw $e;
379
- }
380
- }
381
-
382
- /**
383
- * Returns all blocks.
384
- *
385
- * This method is for internal use only and should never be called
386
- * directly.
387
- *
388
- * @return array An array of blocks
389
- *
390
- * @internal
391
- */
392
- public function getBlocks()
393
- {
394
- return $this->blocks;
395
- }
396
-
397
- public function display(array $context, array $blocks = [])
398
- {
399
- $this->displayWithErrorHandling($this->env->mergeGlobals($context), array_merge($this->blocks, $blocks));
400
- }
401
-
402
- public function render(array $context)
403
- {
404
- $level = ob_get_level();
405
- ob_start();
406
- try {
407
- $this->display($context);
408
- } catch (Exception $e) {
409
- while (ob_get_level() > $level) {
410
- ob_end_clean();
411
- }
412
-
413
- throw $e;
414
- } catch (Throwable $e) {
415
- while (ob_get_level() > $level) {
416
- ob_end_clean();
417
- }
418
-
419
- throw $e;
420
- }
421
-
422
- return ob_get_clean();
423
- }
424
-
425
- protected function displayWithErrorHandling(array $context, array $blocks = [])
426
- {
427
- try {
428
- $this->doDisplay($context, $blocks);
429
- } catch (Twig_Error $e) {
430
- if (!$e->getSourceContext()) {
431
- $e->setSourceContext($this->getSourceContext());
432
- }
433
-
434
- // this is mostly useful for Twig_Error_Loader exceptions
435
- // see Twig_Error_Loader
436
- if (false === $e->getTemplateLine()) {
437
- $e->setTemplateLine(-1);
438
- $e->guess();
439
- }
440
-
441
- throw $e;
442
- } catch (Exception $e) {
443
- throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getSourceContext(), $e);
444
- }
445
- }
446
-
447
- /**
448
- * Auto-generated method to display the template with the given context.
449
- *
450
- * @param array $context An array of parameters to pass to the template
451
- * @param array $blocks An array of blocks to pass to the template
452
- */
453
- abstract protected function doDisplay(array $context, array $blocks = []);
454
-
455
- /**
456
- * Returns a variable from the context.
457
- *
458
- * This method is for internal use only and should never be called
459
- * directly.
460
- *
461
- * This method should not be overridden in a sub-class as this is an
462
- * implementation detail that has been introduced to optimize variable
463
- * access for versions of PHP before 5.4. This is not a way to override
464
- * the way to get a variable value.
465
- *
466
- * @param array $context The context
467
- * @param string $item The variable to return from the context
468
- * @param bool $ignoreStrictCheck Whether to ignore the strict variable check or not
469
- *
470
- * @return mixed The content of the context variable
471
- *
472
- * @throws Twig_Error_Runtime if the variable does not exist and Twig is running in strict mode
473
- *
474
- * @internal
475
- */
476
- final protected function getContext($context, $item, $ignoreStrictCheck = false)
477
- {
478
- if (!array_key_exists($item, $context)) {
479
- if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
480
- return;
481
- }
482
-
483
- throw new Twig_Error_Runtime(sprintf('Variable "%s" does not exist.', $item), -1, $this->getSourceContext());
484
- }
485
-
486
- return $context[$item];
487
- }
488
-
489
- /**
490
- * Returns the attribute value for a given array/object.
491
- *
492
- * @param mixed $object The object or array from where to get the item
493
- * @param mixed $item The item to get from the array or object
494
- * @param array $arguments An array of arguments to pass if the item is an object method
495
- * @param string $type The type of attribute (@see Twig_Template constants)
496
- * @param bool $isDefinedTest Whether this is only a defined check
497
- * @param bool $ignoreStrictCheck Whether to ignore the strict attribute check or not
498
- *
499
- * @return mixed The attribute value, or a Boolean when $isDefinedTest is true, or null when the attribute is not set and $ignoreStrictCheck is true
500
- *
501
- * @throws Twig_Error_Runtime if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false
502
- *
503
- * @internal
504
- */
505
- protected function getAttribute($object, $item, array $arguments = [], $type = self::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
506
- {
507
- // array
508
- if (self::METHOD_CALL !== $type) {
509
- $arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
510
-
511
- if (((is_array($object) || $object instanceof ArrayObject) && (isset($object[$arrayItem]) || array_key_exists($arrayItem, $object)))
512
- || ($object instanceof ArrayAccess && isset($object[$arrayItem]))
513
- ) {
514
- if ($isDefinedTest) {
515
- return true;
516
- }
517
-
518
- return $object[$arrayItem];
519
- }
520
-
521
- if (self::ARRAY_CALL === $type || !is_object($object)) {
522
- if ($isDefinedTest) {
523
- return false;
524
- }
525
-
526
- if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
527
- return;
528
- }
529
-
530
- if ($object instanceof ArrayAccess) {
531
- $message = sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist.', $arrayItem, get_class($object));
532
- } elseif (is_object($object)) {
533
- $message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface.', $item, get_class($object));
534
- } elseif (is_array($object)) {
535
- if (empty($object)) {
536
- $message = sprintf('Key "%s" does not exist as the array is empty.', $arrayItem);
537
- } else {
538
- $message = sprintf('Key "%s" for array with keys "%s" does not exist.', $arrayItem, implode(', ', array_keys($object)));
539
- }
540
- } elseif (self::ARRAY_CALL === $type) {
541
- if (null === $object) {
542
- $message = sprintf('Impossible to access a key ("%s") on a null variable.', $item);
543
- } else {
544
- $message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s").', $item, gettype($object), $object);
545
- }
546
- } elseif (null === $object) {
547
- $message = sprintf('Impossible to access an attribute ("%s") on a null variable.', $item);
548
- } else {
549
- $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s").', $item, gettype($object), $object);
550
- }
551
-
552
- throw new Twig_Error_Runtime($message, -1, $this->getSourceContext());
553
- }
554
- }
555
-
556
- if (!is_object($object)) {
557
- if ($isDefinedTest) {
558
- return false;
559
- }
560
-
561
- if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
562
- return;
563
- }
564
-
565
- if (null === $object) {
566
- $message = sprintf('Impossible to invoke a method ("%s") on a null variable.', $item);
567
- } elseif (is_array($object)) {
568
- $message = sprintf('Impossible to invoke a method ("%s") on an array.', $item);
569
- } else {
570
- $message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").', $item, gettype($object), $object);
571
- }
572
-
573
- throw new Twig_Error_Runtime($message, -1, $this->getSourceContext());
574
- }
575
-
576
- // object property
577
- if (self::METHOD_CALL !== $type && !$object instanceof self) { // Twig_Template does not have public properties, and we don't want to allow access to internal ones
578
- if (isset($object->$item) || array_key_exists((string) $item, $object)) {
579
- if ($isDefinedTest) {
580
- return true;
581
- }
582
-
583
- if ($this->env->hasExtension('Twig_Extension_Sandbox')) {
584
- $this->env->getExtension('Twig_Extension_Sandbox')->checkPropertyAllowed($object, $item);
585
- }
586
-
587
- return $object->$item;
588
- }
589
- }
590
-
591
- $class = get_class($object);
592
-
593
- // object method
594
- if (!isset(self::$cache[$class])) {
595
- // get_class_methods returns all methods accessible in the scope, but we only want public ones to be accessible in templates
596
- if ($object instanceof self) {
597
- $ref = new ReflectionClass($class);
598
- $methods = [];
599
-
600
- foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $refMethod) {
601
- // Accessing the environment from templates is forbidden to prevent untrusted changes to the environment
602
- if ('getenvironment' !== strtolower($refMethod->name)) {
603
- $methods[] = $refMethod->name;
604
- }
605
- }
606
- } else {
607
- $methods = get_class_methods($object);
608
- }
609
- // sort values to have consistent behavior, so that "get" methods win precedence over "is" methods
610
- sort($methods);
611
-
612
- $cache = [];
613
-
614
- foreach ($methods as $method) {
615
- $cache[$method] = $method;
616
- $cache[$lcName = strtolower($method)] = $method;
617
-
618
- if ('g' === $lcName[0] && 0 === strpos($lcName, 'get')) {
619
- $name = substr($method, 3);
620
- $lcName = substr($lcName, 3);
621
- } elseif ('i' === $lcName[0] && 0 === strpos($lcName, 'is')) {
622
- $name = substr($method, 2);
623
- $lcName = substr($lcName, 2);
624
- } else {
625
- continue;
626
- }
627
-
628
- // skip get() and is() methods (in which case, $name is empty)
629
- if ($name) {
630
- if (!isset($cache[$name])) {
631
- $cache[$name] = $method;
632
- }
633
- if (!isset($cache[$lcName])) {
634
- $cache[$lcName] = $method;
635
- }
636
- }
637
- }
638
- self::$cache[$class] = $cache;
639
- }
640
-
641
- $call = false;
642
- if (isset(self::$cache[$class][$item])) {
643
- $method = self::$cache[$class][$item];
644
- } elseif (isset(self::$cache[$class][$lcItem = strtolower($item)])) {
645
- $method = self::$cache[$class][$lcItem];
646
- } elseif (isset(self::$cache[$class]['__call'])) {
647
- $method = $item;
648
- $call = true;
649
- } else {
650
- if ($isDefinedTest) {
651
- return false;
652
- }
653
-
654
- if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
655
- return;
656
- }
657
-
658
- throw new Twig_Error_Runtime(sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, $class), -1, $this->getSourceContext());
659
- }
660
-
661
- if ($isDefinedTest) {
662
- return true;
663
- }
664
-
665
- if ($this->env->hasExtension('Twig_Extension_Sandbox')) {
666
- $this->env->getExtension('Twig_Extension_Sandbox')->checkMethodAllowed($object, $method);
667
- }
668
-
669
- // Some objects throw exceptions when they have __call, and the method we try
670
- // to call is not supported. If ignoreStrictCheck is true, we should return null.
671
- try {
672
- if (!$arguments) {
673
- $ret = $object->$method();
674
- } else {
675
- $ret = call_user_func_array([$object, $method], $arguments);
676
- }
677
- } catch (BadMethodCallException $e) {
678
- if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) {
679
- return;
680
- }
681
- throw $e;
682
- }
683
-
684
- // @deprecated in 1.28
685
- if ($object instanceof Twig_TemplateInterface) {
686
- $self = $object->getTemplateName() === $this->getTemplateName();
687
- $message = sprintf('Calling "%s" on template "%s" from template "%s" is deprecated since version 1.28 and won\'t be supported anymore in 2.0.', $item, $object->getTemplateName(), $this->getTemplateName());
688
- if ('renderBlock' === $method || 'displayBlock' === $method) {
689
- $message .= sprintf(' Use block("%s"%s) instead).', $arguments[0], $self ? '' : ', template');
690
- } elseif ('hasBlock' === $method) {
691
- $message .= sprintf(' Use "block("%s"%s) is defined" instead).', $arguments[0], $self ? '' : ', template');
692
- } elseif ('render' === $method || 'display' === $method) {
693
- $message .= sprintf(' Use include("%s") instead).', $object->getTemplateName());
694
- }
695
- @trigger_error($message, E_USER_DEPRECATED);
696
-
697
- return '' === $ret ? '' : new Twig_Markup($ret, $this->env->getCharset());
698
- }
699
-
700
- return $ret;
701
  }
702
  }
703
-
704
- class_alias('Twig_Template', 'Twig\Template', false);
1
  <?php
2
 
3
+ use Twig\Template;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Template');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Template extends Template
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TemplateInterface.php CHANGED
@@ -9,6 +9,8 @@
9
  * file that was distributed with this source code.
10
  */
11
 
 
 
12
  /**
13
  * Interface implemented by all compiled templates.
14
  *
@@ -42,7 +44,7 @@ interface Twig_TemplateInterface
42
  /**
43
  * Returns the bound environment for this template.
44
  *
45
- * @return Twig_Environment
46
  */
47
  public function getEnvironment();
48
  }
9
  * file that was distributed with this source code.
10
  */
11
 
12
+ use Twig\Environment;
13
+
14
  /**
15
  * Interface implemented by all compiled templates.
16
  *
44
  /**
45
  * Returns the bound environment for this template.
46
  *
47
+ * @return Environment
48
  */
49
  public function getEnvironment();
50
  }
src/lib/vendor/twig/twig/lib/Twig/TemplateWrapper.php CHANGED
@@ -1,137 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Exposes a template to userland.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- final class Twig_TemplateWrapper
18
- {
19
- private $env;
20
- private $template;
21
 
22
- /**
23
- * This method is for internal use only and should never be called
24
- * directly (use Twig_Environment::load() instead).
25
- *
26
- * @internal
27
- */
28
- public function __construct(Twig_Environment $env, Twig_Template $template)
29
  {
30
- $this->env = $env;
31
- $this->template = $template;
32
- }
33
-
34
- /**
35
- * Renders the template.
36
- *
37
- * @param array $context An array of parameters to pass to the template
38
- *
39
- * @return string The rendered template
40
- */
41
- public function render($context = [])
42
- {
43
- // using func_get_args() allows to not expose the blocks argument
44
- // as it should only be used by internal code
45
- return $this->template->render($context, func_num_args() > 1 ? func_get_arg(1) : []);
46
- }
47
-
48
- /**
49
- * Displays the template.
50
- *
51
- * @param array $context An array of parameters to pass to the template
52
- */
53
- public function display($context = [])
54
- {
55
- // using func_get_args() allows to not expose the blocks argument
56
- // as it should only be used by internal code
57
- $this->template->display($context, func_num_args() >= 1 ? func_get_arg(1) : []);
58
- }
59
-
60
- /**
61
- * Checks if a block is defined.
62
- *
63
- * @param string $name The block name
64
- * @param array $context An array of parameters to pass to the template
65
- *
66
- * @return bool
67
- */
68
- public function hasBlock($name, $context = [])
69
- {
70
- return $this->template->hasBlock($name, $context);
71
- }
72
-
73
- /**
74
- * Returns defined block names in the template.
75
- *
76
- * @param array $context An array of parameters to pass to the template
77
- *
78
- * @return string[] An array of defined template block names
79
- */
80
- public function getBlockNames($context = [])
81
- {
82
- return $this->template->getBlockNames($context);
83
- }
84
-
85
- /**
86
- * Renders a template block.
87
- *
88
- * @param string $name The block name to render
89
- * @param array $context An array of parameters to pass to the template
90
- *
91
- * @return string The rendered block
92
- */
93
- public function renderBlock($name, $context = [])
94
- {
95
- $context = $this->env->mergeGlobals($context);
96
- $level = ob_get_level();
97
- ob_start();
98
- try {
99
- $this->template->displayBlock($name, $context);
100
- } catch (Exception $e) {
101
- while (ob_get_level() > $level) {
102
- ob_end_clean();
103
- }
104
-
105
- throw $e;
106
- } catch (Throwable $e) {
107
- while (ob_get_level() > $level) {
108
- ob_end_clean();
109
- }
110
-
111
- throw $e;
112
- }
113
-
114
- return ob_get_clean();
115
- }
116
-
117
- /**
118
- * Displays a template block.
119
- *
120
- * @param string $name The block name to render
121
- * @param array $context An array of parameters to pass to the template
122
- */
123
- public function displayBlock($name, $context = [])
124
- {
125
- $this->template->displayBlock($name, $this->env->mergeGlobals($context));
126
- }
127
-
128
- /**
129
- * @return Twig_Source
130
- */
131
- public function getSourceContext()
132
- {
133
- return $this->template->getSourceContext();
134
  }
135
  }
136
-
137
- class_alias('Twig_TemplateWrapper', 'Twig\TemplateWrapper', false);
1
  <?php
2
 
3
+ use Twig\TemplateWrapper;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TemplateWrapper');
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TemplateWrapper extends TemplateWrapper
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Test.php CHANGED
@@ -9,7 +9,7 @@
9
  * file that was distributed with this source code.
10
  */
11
 
12
- @trigger_error('The Twig_Test class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleTest instead.', E_USER_DEPRECATED);
13
 
14
  /**
15
  * Represents a template test.
9
  * file that was distributed with this source code.
10
  */
11
 
12
+ @trigger_error('The Twig_Test class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigTest instead.', E_USER_DEPRECATED);
13
 
14
  /**
15
  * Represents a template test.
src/lib/vendor/twig/twig/lib/Twig/Token.php CHANGED
@@ -1,207 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Represents a Token.
15
- *
16
- * @author Fabien Potencier <fabien@symfony.com>
17
- *
18
- * @final
19
- */
20
- class Twig_Token
21
- {
22
- protected $value;
23
- protected $type;
24
- protected $lineno;
25
 
26
- const EOF_TYPE = -1;
27
- const TEXT_TYPE = 0;
28
- const BLOCK_START_TYPE = 1;
29
- const VAR_START_TYPE = 2;
30
- const BLOCK_END_TYPE = 3;
31
- const VAR_END_TYPE = 4;
32
- const NAME_TYPE = 5;
33
- const NUMBER_TYPE = 6;
34
- const STRING_TYPE = 7;
35
- const OPERATOR_TYPE = 8;
36
- const PUNCTUATION_TYPE = 9;
37
- const INTERPOLATION_START_TYPE = 10;
38
- const INTERPOLATION_END_TYPE = 11;
39
-
40
- /**
41
- * @param int $type The type of the token
42
- * @param string $value The token value
43
- * @param int $lineno The line position in the source
44
- */
45
- public function __construct($type, $value, $lineno)
46
- {
47
- $this->type = $type;
48
- $this->value = $value;
49
- $this->lineno = $lineno;
50
- }
51
-
52
- public function __toString()
53
  {
54
- return sprintf('%s(%s)', self::typeToString($this->type, true), $this->value);
55
- }
56
-
57
- /**
58
- * Tests the current token for a type and/or a value.
59
- *
60
- * Parameters may be:
61
- * * just type
62
- * * type and value (or array of possible values)
63
- * * just value (or array of possible values) (NAME_TYPE is used as type)
64
- *
65
- * @param array|string|int $type The type to test
66
- * @param array|string|null $values The token value
67
- *
68
- * @return bool
69
- */
70
- public function test($type, $values = null)
71
- {
72
- if (null === $values && !is_int($type)) {
73
- $values = $type;
74
- $type = self::NAME_TYPE;
75
- }
76
-
77
- return ($this->type === $type) && (
78
- null === $values ||
79
- (is_array($values) && in_array($this->value, $values)) ||
80
- $this->value == $values
81
- );
82
- }
83
-
84
- /**
85
- * @return int
86
- */
87
- public function getLine()
88
- {
89
- return $this->lineno;
90
- }
91
-
92
- /**
93
- * @return int
94
- */
95
- public function getType()
96
- {
97
- return $this->type;
98
- }
99
-
100
- /**
101
- * @return string
102
- */
103
- public function getValue()
104
- {
105
- return $this->value;
106
- }
107
-
108
- /**
109
- * Returns the constant representation (internal) of a given type.
110
- *
111
- * @param int $type The type as an integer
112
- * @param bool $short Whether to return a short representation or not
113
- *
114
- * @return string The string representation
115
- */
116
- public static function typeToString($type, $short = false)
117
- {
118
- switch ($type) {
119
- case self::EOF_TYPE:
120
- $name = 'EOF_TYPE';
121
- break;
122
- case self::TEXT_TYPE:
123
- $name = 'TEXT_TYPE';
124
- break;
125
- case self::BLOCK_START_TYPE:
126
- $name = 'BLOCK_START_TYPE';
127
- break;
128
- case self::VAR_START_TYPE:
129
- $name = 'VAR_START_TYPE';
130
- break;
131
- case self::BLOCK_END_TYPE:
132
- $name = 'BLOCK_END_TYPE';
133
- break;
134
- case self::VAR_END_TYPE:
135
- $name = 'VAR_END_TYPE';
136
- break;
137
- case self::NAME_TYPE:
138
- $name = 'NAME_TYPE';
139
- break;
140
- case self::NUMBER_TYPE:
141
- $name = 'NUMBER_TYPE';
142
- break;
143
- case self::STRING_TYPE:
144
- $name = 'STRING_TYPE';
145
- break;
146
- case self::OPERATOR_TYPE:
147
- $name = 'OPERATOR_TYPE';
148
- break;
149
- case self::PUNCTUATION_TYPE:
150
- $name = 'PUNCTUATION_TYPE';
151
- break;
152
- case self::INTERPOLATION_START_TYPE:
153
- $name = 'INTERPOLATION_START_TYPE';
154
- break;
155
- case self::INTERPOLATION_END_TYPE:
156
- $name = 'INTERPOLATION_END_TYPE';
157
- break;
158
- default:
159
- throw new LogicException(sprintf('Token of type "%s" does not exist.', $type));
160
- }
161
-
162
- return $short ? $name : 'Twig_Token::'.$name;
163
- }
164
-
165
- /**
166
- * Returns the English representation of a given type.
167
- *
168
- * @param int $type The type as an integer
169
- *
170
- * @return string The string representation
171
- */
172
- public static function typeToEnglish($type)
173
- {
174
- switch ($type) {
175
- case self::EOF_TYPE:
176
- return 'end of template';
177
- case self::TEXT_TYPE:
178
- return 'text';
179
- case self::BLOCK_START_TYPE:
180
- return 'begin of statement block';
181
- case self::VAR_START_TYPE:
182
- return 'begin of print statement';
183
- case self::BLOCK_END_TYPE:
184
- return 'end of statement block';
185
- case self::VAR_END_TYPE:
186
- return 'end of print statement';
187
- case self::NAME_TYPE:
188
- return 'name';
189
- case self::NUMBER_TYPE:
190
- return 'number';
191
- case self::STRING_TYPE:
192
- return 'string';
193
- case self::OPERATOR_TYPE:
194
- return 'operator';
195
- case self::PUNCTUATION_TYPE:
196
- return 'punctuation';
197
- case self::INTERPOLATION_START_TYPE:
198
- return 'begin of string interpolation';
199
- case self::INTERPOLATION_END_TYPE:
200
- return 'end of string interpolation';
201
- default:
202
- throw new LogicException(sprintf('Token of type "%s" does not exist.', $type));
203
- }
204
  }
205
  }
206
-
207
- class_alias('Twig_Token', 'Twig\Token', false);
1
  <?php
2
 
3
+ use Twig\Token;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Token');
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Token extends Token
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser.php CHANGED
@@ -1,33 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Base class for all token parsers.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- abstract class Twig_TokenParser implements Twig_TokenParserInterface
18
- {
19
- /**
20
- * @var Twig_Parser
21
- */
22
- protected $parser;
23
 
24
- /**
25
- * Sets the parser associated with this token parser.
26
- */
27
- public function setParser(Twig_Parser $parser)
28
  {
29
- $this->parser = $parser;
30
  }
31
  }
32
-
33
- class_alias('Twig_TokenParser', 'Twig\TokenParser\AbstractTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\AbstractTokenParser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\AbstractTokenParser');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser extends AbstractTokenParser
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/AutoEscape.php CHANGED
@@ -1,83 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Marks a section of a template to be escaped or not.
14
- *
15
- * <pre>
16
- * {% autoescape true %}
17
- * Everything will be automatically escaped in this block
18
- * {% endautoescape %}
19
- *
20
- * {% autoescape false %}
21
- * Everything will be outputed as is in this block
22
- * {% endautoescape %}
23
- *
24
- * {% autoescape true js %}
25
- * Everything will be automatically escaped in this block
26
- * using the js escaping strategy
27
- * {% endautoescape %}
28
- * </pre>
29
- *
30
- * @final
31
- */
32
- class Twig_TokenParser_AutoEscape extends Twig_TokenParser
33
- {
34
- public function parse(Twig_Token $token)
35
- {
36
- $lineno = $token->getLine();
37
- $stream = $this->parser->getStream();
38
-
39
- if ($stream->test(Twig_Token::BLOCK_END_TYPE)) {
40
- $value = 'html';
41
- } else {
42
- $expr = $this->parser->getExpressionParser()->parseExpression();
43
- if (!$expr instanceof Twig_Node_Expression_Constant) {
44
- throw new Twig_Error_Syntax('An escaping strategy must be a string or a bool.', $stream->getCurrent()->getLine(), $stream->getSourceContext());
45
- }
46
- $value = $expr->getAttribute('value');
47
-
48
- $compat = true === $value || false === $value;
49
-
50
- if (true === $value) {
51
- $value = 'html';
52
- }
53
-
54
- if ($compat && $stream->test(Twig_Token::NAME_TYPE)) {
55
- @trigger_error('Using the autoescape tag with "true" or "false" before the strategy name is deprecated since version 1.21.', E_USER_DEPRECATED);
56
-
57
- if (false === $value) {
58
- throw new Twig_Error_Syntax('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->getSourceContext());
59
- }
60
-
61
- $value = $stream->next()->getValue();
62
- }
63
- }
64
 
65
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
66
- $body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
67
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
68
-
69
- return new Twig_Node_AutoEscape($value, $body, $lineno, $this->getTag());
70
- }
71
-
72
- public function decideBlockEnd(Twig_Token $token)
73
  {
74
- return $token->test('endautoescape');
75
- }
76
-
77
- public function getTag()
78
- {
79
- return 'autoescape';
80
  }
81
  }
82
-
83
- class_alias('Twig_TokenParser_AutoEscape', 'Twig\TokenParser\AutoEscapeTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\AutoEscapeTokenParser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\AutoEscapeTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_AutoEscape extends AutoEscapeTokenParser
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/Block.php CHANGED
@@ -1,73 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Marks a section of a template as being reusable.
15
- *
16
- * <pre>
17
- * {% block head %}
18
- * <link rel="stylesheet" href="style.css" />
19
- * <title>{% block title %}{% endblock %} - My Webpage</title>
20
- * {% endblock %}
21
- * </pre>
22
- *
23
- * @final
24
- */
25
- class Twig_TokenParser_Block extends Twig_TokenParser
26
- {
27
- public function parse(Twig_Token $token)
28
- {
29
- $lineno = $token->getLine();
30
- $stream = $this->parser->getStream();
31
- $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
32
- if ($this->parser->hasBlock($name)) {
33
- throw new Twig_Error_Syntax(sprintf("The block '%s' has already been defined line %d.", $name, $this->parser->getBlock($name)->getTemplateLine()), $stream->getCurrent()->getLine(), $stream->getSourceContext());
34
- }
35
- $this->parser->setBlock($name, $block = new Twig_Node_Block($name, new Twig_Node([]), $lineno));
36
- $this->parser->pushLocalScope();
37
- $this->parser->pushBlockStack($name);
38
-
39
- if ($stream->nextIf(Twig_Token::BLOCK_END_TYPE)) {
40
- $body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
41
- if ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) {
42
- $value = $token->getValue();
43
-
44
- if ($value != $name) {
45
- throw new Twig_Error_Syntax(sprintf('Expected endblock for block "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext());
46
- }
47
- }
48
- } else {
49
- $body = new Twig_Node([
50
- new Twig_Node_Print($this->parser->getExpressionParser()->parseExpression(), $lineno),
51
- ]);
52
- }
53
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
54
-
55
- $block->setNode('body', $body);
56
- $this->parser->popBlockStack();
57
- $this->parser->popLocalScope();
58
-
59
- return new Twig_Node_BlockReference($name, $lineno, $this->getTag());
60
- }
61
 
62
- public function decideBlockEnd(Twig_Token $token)
 
63
  {
64
- return $token->test('endblock');
65
- }
66
-
67
- public function getTag()
68
- {
69
- return 'block';
70
  }
71
  }
72
-
73
- class_alias('Twig_TokenParser_Block', 'Twig\TokenParser\BlockTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\BlockTokenParser;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\BlockTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_Block extends BlockTokenParser
9
  {
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/Deprecated.php CHANGED
@@ -1,42 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Deprecates a section of a template.
14
- *
15
- * <pre>
16
- * {% deprecated 'The "base.twig" template is deprecated, use "layout.twig" instead.' %}
17
- *
18
- * {% extends 'layout.html.twig' %}
19
- * </pre>
20
- *
21
- * @author Yonel Ceruto <yonelceruto@gmail.com>
22
- *
23
- * @final
24
- */
25
- class Twig_TokenParser_Deprecated extends Twig_TokenParser
26
- {
27
- public function parse(Twig_Token $token)
28
- {
29
- $expr = $this->parser->getExpressionParser()->parseExpression();
30
-
31
- $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
32
 
33
- return new Twig_Node_Deprecated($expr, $token->getLine(), $this->getTag());
34
- }
35
-
36
- public function getTag()
37
  {
38
- return 'deprecated';
39
  }
40
  }
41
-
42
- class_alias('Twig_TokenParser_Deprecated', 'Twig\TokenParser\DeprecatedTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\DeprecatedTokenParser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\DeprecatedTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_Deprecated extends DeprecatedTokenParser
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/Do.php CHANGED
@@ -1,34 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Evaluates an expression, discarding the returned value.
14
- *
15
- * @final
16
- */
17
- class Twig_TokenParser_Do extends Twig_TokenParser
18
- {
19
- public function parse(Twig_Token $token)
20
- {
21
- $expr = $this->parser->getExpressionParser()->parseExpression();
22
-
23
- $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
24
 
25
- return new Twig_Node_Do($expr, $token->getLine(), $this->getTag());
26
- }
27
-
28
- public function getTag()
29
  {
30
- return 'do';
31
  }
32
  }
33
-
34
- class_alias('Twig_TokenParser_Do', 'Twig\TokenParser\DoTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\DoTokenParser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\DoTokenParser');
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_Do extends DoTokenParser
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/Embed.php CHANGED
@@ -1,67 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Embeds a template.
14
- *
15
- * @final
16
- */
17
- class Twig_TokenParser_Embed extends Twig_TokenParser_Include
18
- {
19
- public function parse(Twig_Token $token)
20
- {
21
- $stream = $this->parser->getStream();
22
-
23
- $parent = $this->parser->getExpressionParser()->parseExpression();
24
-
25
- list($variables, $only, $ignoreMissing) = $this->parseArguments();
26
-
27
- $parentToken = $fakeParentToken = new Twig_Token(Twig_Token::STRING_TYPE, '__parent__', $token->getLine());
28
- if ($parent instanceof Twig_Node_Expression_Constant) {
29
- $parentToken = new Twig_Token(Twig_Token::STRING_TYPE, $parent->getAttribute('value'), $token->getLine());
30
- } elseif ($parent instanceof Twig_Node_Expression_Name) {
31
- $parentToken = new Twig_Token(Twig_Token::NAME_TYPE, $parent->getAttribute('name'), $token->getLine());
32
- }
33
-
34
- // inject a fake parent to make the parent() function work
35
- $stream->injectTokens([
36
- new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', $token->getLine()),
37
- new Twig_Token(Twig_Token::NAME_TYPE, 'extends', $token->getLine()),
38
- $parentToken,
39
- new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', $token->getLine()),
40
- ]);
41
-
42
- $module = $this->parser->parse($stream, [$this, 'decideBlockEnd'], true);
43
-
44
- // override the parent with the correct one
45
- if ($fakeParentToken === $parentToken) {
46
- $module->setNode('parent', $parent);
47
- }
48
-
49
- $this->parser->embedTemplate($module);
50
 
51
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
52
-
53
- return new Twig_Node_Embed($module->getTemplateName(), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
54
- }
55
-
56
- public function decideBlockEnd(Twig_Token $token)
57
  {
58
- return $token->test('endembed');
59
- }
60
-
61
- public function getTag()
62
- {
63
- return 'embed';
64
  }
65
  }
66
-
67
- class_alias('Twig_TokenParser_Embed', 'Twig\TokenParser\EmbedTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\EmbedTokenParser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\EmbedTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_Embed extends EmbedTokenParser
 
 
 
 
9
  {
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/Extends.php CHANGED
@@ -1,46 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Extends a template by another one.
15
- *
16
- * <pre>
17
- * {% extends "base.html" %}
18
- * </pre>
19
- *
20
- * @final
21
- */
22
- class Twig_TokenParser_Extends extends Twig_TokenParser
23
- {
24
- public function parse(Twig_Token $token)
25
- {
26
- $stream = $this->parser->getStream();
27
-
28
- if (!$this->parser->isMainScope()) {
29
- throw new Twig_Error_Syntax('Cannot extend from a block.', $token->getLine(), $stream->getSourceContext());
30
- }
31
-
32
- if (null !== $this->parser->getParent()) {
33
- throw new Twig_Error_Syntax('Multiple extends tags are forbidden.', $token->getLine(), $stream->getSourceContext());
34
- }
35
- $this->parser->setParent($this->parser->getExpressionParser()->parseExpression());
36
 
37
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
38
- }
39
-
40
- public function getTag()
41
  {
42
- return 'extends';
43
  }
44
  }
45
-
46
- class_alias('Twig_TokenParser_Extends', 'Twig\TokenParser\ExtendsTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\ExtendsTokenParser;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\ExtendsTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_Extends extends ExtendsTokenParser
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/Filter.php CHANGED
@@ -1,53 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Filters a section of a template by applying filters.
14
- *
15
- * <pre>
16
- * {% filter upper %}
17
- * This text becomes uppercase
18
- * {% endfilter %}
19
- * </pre>
20
- *
21
- * @final
22
- */
23
- class Twig_TokenParser_Filter extends Twig_TokenParser
24
- {
25
- public function parse(Twig_Token $token)
26
- {
27
- $name = $this->parser->getVarName();
28
- $ref = new Twig_Node_Expression_BlockReference(new Twig_Node_Expression_Constant($name, $token->getLine()), null, $token->getLine(), $this->getTag());
29
-
30
- $filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag());
31
- $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
32
-
33
- $body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
34
- $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
35
-
36
- $block = new Twig_Node_Block($name, $body, $token->getLine());
37
- $this->parser->setBlock($name, $block);
38
-
39
- return new Twig_Node_Print($filter, $token->getLine(), $this->getTag());
40
- }
41
 
42
- public function decideBlockEnd(Twig_Token $token)
 
43
  {
44
- return $token->test('endfilter');
45
- }
46
-
47
- public function getTag()
48
- {
49
- return 'filter';
50
  }
51
  }
52
-
53
- class_alias('Twig_TokenParser_Filter', 'Twig\TokenParser\FilterTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\FilterTokenParser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\FilterTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_Filter extends FilterTokenParser
9
  {
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/Flush.php CHANGED
@@ -1,34 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Flushes the output to the client.
14
- *
15
- * @see flush()
16
- *
17
- * @final
18
- */
19
- class Twig_TokenParser_Flush extends Twig_TokenParser
20
- {
21
- public function parse(Twig_Token $token)
22
- {
23
- $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
24
-
25
- return new Twig_Node_Flush($token->getLine(), $this->getTag());
26
- }
27
 
28
- public function getTag()
 
29
  {
30
- return 'flush';
31
  }
32
  }
33
-
34
- class_alias('Twig_TokenParser_Flush', 'Twig\TokenParser\FlushTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\FlushTokenParser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\FlushTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_Flush extends FlushTokenParser
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/For.php CHANGED
@@ -1,127 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Loops over each item of a sequence.
15
- *
16
- * <pre>
17
- * <ul>
18
- * {% for user in users %}
19
- * <li>{{ user.username|e }}</li>
20
- * {% endfor %}
21
- * </ul>
22
- * </pre>
23
- *
24
- * @final
25
- */
26
- class Twig_TokenParser_For extends Twig_TokenParser
27
- {
28
- public function parse(Twig_Token $token)
29
- {
30
- $lineno = $token->getLine();
31
- $stream = $this->parser->getStream();
32
- $targets = $this->parser->getExpressionParser()->parseAssignmentExpression();
33
- $stream->expect(Twig_Token::OPERATOR_TYPE, 'in');
34
- $seq = $this->parser->getExpressionParser()->parseExpression();
35
-
36
- $ifexpr = null;
37
- if ($stream->nextIf(Twig_Token::NAME_TYPE, 'if')) {
38
- $ifexpr = $this->parser->getExpressionParser()->parseExpression();
39
- }
40
-
41
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
42
- $body = $this->parser->subparse([$this, 'decideForFork']);
43
- if ('else' == $stream->next()->getValue()) {
44
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
45
- $else = $this->parser->subparse([$this, 'decideForEnd'], true);
46
- } else {
47
- $else = null;
48
- }
49
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
50
-
51
- if (count($targets) > 1) {
52
- $keyTarget = $targets->getNode(0);
53
- $keyTarget = new Twig_Node_Expression_AssignName($keyTarget->getAttribute('name'), $keyTarget->getTemplateLine());
54
- $valueTarget = $targets->getNode(1);
55
- $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine());
56
- } else {
57
- $keyTarget = new Twig_Node_Expression_AssignName('_key', $lineno);
58
- $valueTarget = $targets->getNode(0);
59
- $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine());
60
- }
61
-
62
- if ($ifexpr) {
63
- $this->checkLoopUsageCondition($stream, $ifexpr);
64
- $this->checkLoopUsageBody($stream, $body);
65
- }
66
-
67
- return new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, $lineno, $this->getTag());
68
- }
69
 
70
- public function decideForFork(Twig_Token $token)
 
71
  {
72
- return $token->test(['else', 'endfor']);
73
- }
74
-
75
- public function decideForEnd(Twig_Token $token)
76
- {
77
- return $token->test('endfor');
78
- }
79
-
80
- // the loop variable cannot be used in the condition
81
- protected function checkLoopUsageCondition(Twig_TokenStream $stream, Twig_NodeInterface $node)
82
- {
83
- if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
84
- throw new Twig_Error_Syntax('The "loop" variable cannot be used in a looping condition.', $node->getTemplateLine(), $stream->getSourceContext());
85
- }
86
-
87
- foreach ($node as $n) {
88
- if (!$n) {
89
- continue;
90
- }
91
-
92
- $this->checkLoopUsageCondition($stream, $n);
93
- }
94
- }
95
-
96
- // check usage of non-defined loop-items
97
- // it does not catch all problems (for instance when a for is included into another or when the variable is used in an include)
98
- protected function checkLoopUsageBody(Twig_TokenStream $stream, Twig_NodeInterface $node)
99
- {
100
- if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) {
101
- $attribute = $node->getNode('attribute');
102
- if ($attribute instanceof Twig_Node_Expression_Constant && in_array($attribute->getAttribute('value'), ['length', 'revindex0', 'revindex', 'last'])) {
103
- throw new Twig_Error_Syntax(sprintf('The "loop.%s" variable is not defined when looping with a condition.', $attribute->getAttribute('value')), $node->getTemplateLine(), $stream->getSourceContext());
104
- }
105
- }
106
-
107
- // should check for parent.loop.XXX usage
108
- if ($node instanceof Twig_Node_For) {
109
- return;
110
- }
111
-
112
- foreach ($node as $n) {
113
- if (!$n) {
114
- continue;
115
- }
116
-
117
- $this->checkLoopUsageBody($stream, $n);
118
- }
119
- }
120
-
121
- public function getTag()
122
- {
123
- return 'for';
124
  }
125
  }
126
-
127
- class_alias('Twig_TokenParser_For', 'Twig\TokenParser\ForTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\ForTokenParser;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\ForTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_For extends ForTokenParser
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/From.php CHANGED
@@ -1,66 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Imports macros.
14
- *
15
- * <pre>
16
- * {% from 'forms.html' import forms %}
17
- * </pre>
18
- *
19
- * @final
20
- */
21
- class Twig_TokenParser_From extends Twig_TokenParser
22
- {
23
- public function parse(Twig_Token $token)
24
- {
25
- $macro = $this->parser->getExpressionParser()->parseExpression();
26
- $stream = $this->parser->getStream();
27
- $stream->expect('import');
28
-
29
- $targets = [];
30
- do {
31
- $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
32
-
33
- $alias = $name;
34
- if ($stream->nextIf('as')) {
35
- $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
36
- }
37
-
38
- $targets[$name] = $alias;
39
-
40
- if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) {
41
- break;
42
- }
43
- } while (true);
44
-
45
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
46
 
47
- $node = new Twig_Node_Import($macro, new Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()), $token->getLine(), $this->getTag());
48
-
49
- foreach ($targets as $name => $alias) {
50
- if ($this->parser->isReservedMacroName($name)) {
51
- throw new Twig_Error_Syntax(sprintf('"%s" cannot be an imported macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext());
52
- }
53
-
54
- $this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var'));
55
- }
56
-
57
- return $node;
58
- }
59
-
60
- public function getTag()
61
  {
62
- return 'from';
63
  }
64
  }
65
-
66
- class_alias('Twig_TokenParser_From', 'Twig\TokenParser\FromTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\FromTokenParser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\FromTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_From extends FromTokenParser
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/If.php CHANGED
@@ -1,86 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Tests a condition.
15
- *
16
- * <pre>
17
- * {% if users %}
18
- * <ul>
19
- * {% for user in users %}
20
- * <li>{{ user.username|e }}</li>
21
- * {% endfor %}
22
- * </ul>
23
- * {% endif %}
24
- * </pre>
25
- *
26
- * @final
27
- */
28
- class Twig_TokenParser_If extends Twig_TokenParser
29
- {
30
- public function parse(Twig_Token $token)
31
- {
32
- $lineno = $token->getLine();
33
- $expr = $this->parser->getExpressionParser()->parseExpression();
34
- $stream = $this->parser->getStream();
35
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
36
- $body = $this->parser->subparse([$this, 'decideIfFork']);
37
- $tests = [$expr, $body];
38
- $else = null;
39
-
40
- $end = false;
41
- while (!$end) {
42
- switch ($stream->next()->getValue()) {
43
- case 'else':
44
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
45
- $else = $this->parser->subparse([$this, 'decideIfEnd']);
46
- break;
47
-
48
- case 'elseif':
49
- $expr = $this->parser->getExpressionParser()->parseExpression();
50
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
51
- $body = $this->parser->subparse([$this, 'decideIfFork']);
52
- $tests[] = $expr;
53
- $tests[] = $body;
54
- break;
55
-
56
- case 'endif':
57
- $end = true;
58
- break;
59
-
60
- default:
61
- throw new Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d).', $lineno), $stream->getCurrent()->getLine(), $stream->getSourceContext());
62
- }
63
- }
64
-
65
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
66
-
67
- return new Twig_Node_If(new Twig_Node($tests), $else, $lineno, $this->getTag());
68
- }
69
 
70
- public function decideIfFork(Twig_Token $token)
 
71
  {
72
- return $token->test(['elseif', 'else', 'endif']);
73
- }
74
-
75
- public function decideIfEnd(Twig_Token $token)
76
- {
77
- return $token->test(['endif']);
78
- }
79
-
80
- public function getTag()
81
- {
82
- return 'if';
83
  }
84
  }
85
-
86
- class_alias('Twig_TokenParser_If', 'Twig\TokenParser\IfTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\IfTokenParser;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\IfTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_If extends IfTokenParser
9
  {
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/Import.php CHANGED
@@ -1,41 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Imports macros.
14
- *
15
- * <pre>
16
- * {% import 'forms.html' as forms %}
17
- * </pre>
18
- *
19
- * @final
20
- */
21
- class Twig_TokenParser_Import extends Twig_TokenParser
22
- {
23
- public function parse(Twig_Token $token)
24
- {
25
- $macro = $this->parser->getExpressionParser()->parseExpression();
26
- $this->parser->getStream()->expect('as');
27
- $var = new Twig_Node_Expression_AssignName($this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(), $token->getLine());
28
- $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
29
-
30
- $this->parser->addImportedSymbol('template', $var->getAttribute('name'));
31
 
32
- return new Twig_Node_Import($macro, $var, $token->getLine(), $this->getTag());
33
- }
34
-
35
- public function getTag()
36
  {
37
- return 'import';
38
  }
39
  }
40
-
41
- class_alias('Twig_TokenParser_Import', 'Twig\TokenParser\ImportTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\ImportTokenParser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\ImportTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_Import extends ImportTokenParser
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/Include.php CHANGED
@@ -1,65 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Includes a template.
15
- *
16
- * <pre>
17
- * {% include 'header.html' %}
18
- * Body
19
- * {% include 'footer.html' %}
20
- * </pre>
21
- */
22
- class Twig_TokenParser_Include extends Twig_TokenParser
23
- {
24
- public function parse(Twig_Token $token)
25
- {
26
- $expr = $this->parser->getExpressionParser()->parseExpression();
27
-
28
- list($variables, $only, $ignoreMissing) = $this->parseArguments();
29
-
30
- return new Twig_Node_Include($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
31
- }
32
-
33
- protected function parseArguments()
34
- {
35
- $stream = $this->parser->getStream();
36
-
37
- $ignoreMissing = false;
38
- if ($stream->nextIf(Twig_Token::NAME_TYPE, 'ignore')) {
39
- $stream->expect(Twig_Token::NAME_TYPE, 'missing');
40
 
41
- $ignoreMissing = true;
42
- }
43
-
44
- $variables = null;
45
- if ($stream->nextIf(Twig_Token::NAME_TYPE, 'with')) {
46
- $variables = $this->parser->getExpressionParser()->parseExpression();
47
- }
48
-
49
- $only = false;
50
- if ($stream->nextIf(Twig_Token::NAME_TYPE, 'only')) {
51
- $only = true;
52
- }
53
-
54
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
55
-
56
- return [$variables, $only, $ignoreMissing];
57
- }
58
-
59
- public function getTag()
60
  {
61
- return 'include';
62
  }
63
  }
64
-
65
- class_alias('Twig_TokenParser_Include', 'Twig\TokenParser\IncludeTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\IncludeTokenParser;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\IncludeTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_Include extends IncludeTokenParser
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/Macro.php CHANGED
@@ -1,60 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Defines a macro.
14
- *
15
- * <pre>
16
- * {% macro input(name, value, type, size) %}
17
- * <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
18
- * {% endmacro %}
19
- * </pre>
20
- *
21
- * @final
22
- */
23
- class Twig_TokenParser_Macro extends Twig_TokenParser
24
- {
25
- public function parse(Twig_Token $token)
26
- {
27
- $lineno = $token->getLine();
28
- $stream = $this->parser->getStream();
29
- $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
30
-
31
- $arguments = $this->parser->getExpressionParser()->parseArguments(true, true);
32
-
33
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
34
- $this->parser->pushLocalScope();
35
- $body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
36
- if ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) {
37
- $value = $token->getValue();
38
-
39
- if ($value != $name) {
40
- throw new Twig_Error_Syntax(sprintf('Expected endmacro for macro "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext());
41
- }
42
- }
43
- $this->parser->popLocalScope();
44
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
45
-
46
- $this->parser->setMacro($name, new Twig_Node_Macro($name, new Twig_Node_Body([$body]), $arguments, $lineno, $this->getTag()));
47
- }
48
 
49
- public function decideBlockEnd(Twig_Token $token)
 
50
  {
51
- return $token->test('endmacro');
52
- }
53
-
54
- public function getTag()
55
- {
56
- return 'macro';
57
  }
58
  }
59
-
60
- class_alias('Twig_TokenParser_Macro', 'Twig\TokenParser\MacroTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\MacroTokenParser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\MacroTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_Macro extends MacroTokenParser
9
  {
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/Sandbox.php CHANGED
@@ -1,61 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Marks a section of a template as untrusted code that must be evaluated in the sandbox mode.
14
- *
15
- * <pre>
16
- * {% sandbox %}
17
- * {% include 'user.html' %}
18
- * {% endsandbox %}
19
- * </pre>
20
- *
21
- * @see https://twig.symfony.com/doc/api.html#sandbox-extension for details
22
- *
23
- * @final
24
- */
25
- class Twig_TokenParser_Sandbox extends Twig_TokenParser
26
- {
27
- public function parse(Twig_Token $token)
28
- {
29
- $stream = $this->parser->getStream();
30
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
31
- $body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
32
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
33
-
34
- // in a sandbox tag, only include tags are allowed
35
- if (!$body instanceof Twig_Node_Include) {
36
- foreach ($body as $node) {
37
- if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) {
38
- continue;
39
- }
40
-
41
- if (!$node instanceof Twig_Node_Include) {
42
- throw new Twig_Error_Syntax('Only "include" tags are allowed within a "sandbox" section.', $node->getTemplateLine(), $stream->getSourceContext());
43
- }
44
- }
45
- }
46
-
47
- return new Twig_Node_Sandbox($body, $token->getLine(), $this->getTag());
48
- }
49
 
50
- public function decideBlockEnd(Twig_Token $token)
 
51
  {
52
- return $token->test('endsandbox');
53
- }
54
-
55
- public function getTag()
56
- {
57
- return 'sandbox';
58
  }
59
  }
60
-
61
- class_alias('Twig_TokenParser_Sandbox', 'Twig\TokenParser\SandboxTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\SandboxTokenParser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\SandboxTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_Sandbox extends SandboxTokenParser
9
  {
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/Set.php CHANGED
@@ -1,75 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Defines a variable.
14
- *
15
- * <pre>
16
- * {% set foo = 'foo' %}
17
- *
18
- * {% set foo = [1, 2] %}
19
- *
20
- * {% set foo = {'foo': 'bar'} %}
21
- *
22
- * {% set foo = 'foo' ~ 'bar' %}
23
- *
24
- * {% set foo, bar = 'foo', 'bar' %}
25
- *
26
- * {% set foo %}Some content{% endset %}
27
- * </pre>
28
- *
29
- * @final
30
- */
31
- class Twig_TokenParser_Set extends Twig_TokenParser
32
- {
33
- public function parse(Twig_Token $token)
34
- {
35
- $lineno = $token->getLine();
36
- $stream = $this->parser->getStream();
37
- $names = $this->parser->getExpressionParser()->parseAssignmentExpression();
38
-
39
- $capture = false;
40
- if ($stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) {
41
- $values = $this->parser->getExpressionParser()->parseMultitargetExpression();
42
-
43
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
44
-
45
- if (count($names) !== count($values)) {
46
- throw new Twig_Error_Syntax('When using set, you must have the same number of variables and assignments.', $stream->getCurrent()->getLine(), $stream->getSourceContext());
47
- }
48
- } else {
49
- $capture = true;
50
-
51
- if (count($names) > 1) {
52
- throw new Twig_Error_Syntax('When using set with a block, you cannot have a multi-target.', $stream->getCurrent()->getLine(), $stream->getSourceContext());
53
- }
54
-
55
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
56
-
57
- $values = $this->parser->subparse([$this, 'decideBlockEnd'], true);
58
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
59
- }
60
 
61
- return new Twig_Node_Set($capture, $names, $values, $lineno, $this->getTag());
62
- }
63
-
64
- public function decideBlockEnd(Twig_Token $token)
65
- {
66
- return $token->test('endset');
67
- }
68
-
69
- public function getTag()
70
  {
71
- return 'set';
72
  }
73
  }
74
-
75
- class_alias('Twig_TokenParser_Set', 'Twig\TokenParser\SetTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\SetTokenParser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\SetTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_Set extends SetTokenParser
 
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/Spaceless.php CHANGED
@@ -1,51 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Remove whitespaces between HTML tags.
14
- *
15
- * <pre>
16
- * {% spaceless %}
17
- * <div>
18
- * <strong>foo</strong>
19
- * </div>
20
- * {% endspaceless %}
21
- *
22
- * {# output will be <div><strong>foo</strong></div> #}
23
- * </pre>
24
- *
25
- * @final
26
- */
27
- class Twig_TokenParser_Spaceless extends Twig_TokenParser
28
- {
29
- public function parse(Twig_Token $token)
30
- {
31
- $lineno = $token->getLine();
32
-
33
- $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
34
- $body = $this->parser->subparse([$this, 'decideSpacelessEnd'], true);
35
- $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
36
-
37
- return new Twig_Node_Spaceless($body, $lineno, $this->getTag());
38
- }
39
 
40
- public function decideSpacelessEnd(Twig_Token $token)
 
41
  {
42
- return $token->test('endspaceless');
43
- }
44
-
45
- public function getTag()
46
- {
47
- return 'spaceless';
48
  }
49
  }
50
-
51
- class_alias('Twig_TokenParser_Spaceless', 'Twig\TokenParser\SpacelessTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\SpacelessTokenParser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\SpacelessTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_Spaceless extends SpacelessTokenParser
9
  {
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/Use.php CHANGED
@@ -1,70 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Imports blocks defined in another template into the current template.
14
- *
15
- * <pre>
16
- * {% extends "base.html" %}
17
- *
18
- * {% use "blocks.html" %}
19
- *
20
- * {% block title %}{% endblock %}
21
- * {% block content %}{% endblock %}
22
- * </pre>
23
- *
24
- * @see https://twig.symfony.com/doc/templates.html#horizontal-reuse for details.
25
- *
26
- * @final
27
- */
28
- class Twig_TokenParser_Use extends Twig_TokenParser
29
- {
30
- public function parse(Twig_Token $token)
31
- {
32
- $template = $this->parser->getExpressionParser()->parseExpression();
33
- $stream = $this->parser->getStream();
34
-
35
- if (!$template instanceof Twig_Node_Expression_Constant) {
36
- throw new Twig_Error_Syntax('The template references in a "use" statement must be a string.', $stream->getCurrent()->getLine(), $stream->getSourceContext());
37
- }
38
-
39
- $targets = [];
40
- if ($stream->nextIf('with')) {
41
- do {
42
- $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
43
-
44
- $alias = $name;
45
- if ($stream->nextIf('as')) {
46
- $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
47
- }
48
-
49
- $targets[$name] = new Twig_Node_Expression_Constant($alias, -1);
50
-
51
- if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) {
52
- break;
53
- }
54
- } while (true);
55
- }
56
 
57
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
58
-
59
- $this->parser->addTrait(new Twig_Node(['template' => $template, 'targets' => new Twig_Node($targets)]));
60
-
61
- return new Twig_Node();
62
- }
63
-
64
- public function getTag()
65
  {
66
- return 'use';
67
  }
68
  }
69
-
70
- class_alias('Twig_TokenParser_Use', 'Twig\TokenParser\UseTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\UseTokenParser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\UseTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_Use extends UseTokenParser
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParser/With.php CHANGED
@@ -1,52 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Creates a nested scope.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- *
17
- * @final
18
- */
19
- class Twig_TokenParser_With extends Twig_TokenParser
20
- {
21
- public function parse(Twig_Token $token)
22
- {
23
- $stream = $this->parser->getStream();
24
-
25
- $variables = null;
26
- $only = false;
27
- if (!$stream->test(Twig_Token::BLOCK_END_TYPE)) {
28
- $variables = $this->parser->getExpressionParser()->parseExpression();
29
- $only = $stream->nextIf(Twig_Token::NAME_TYPE, 'only');
30
- }
31
-
32
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
33
 
34
- $body = $this->parser->subparse([$this, 'decideWithEnd'], true);
35
-
36
- $stream->expect(Twig_Token::BLOCK_END_TYPE);
37
-
38
- return new Twig_Node_With($body, $variables, $only, $token->getLine(), $this->getTag());
39
- }
40
-
41
- public function decideWithEnd(Twig_Token $token)
42
  {
43
- return $token->test('endwith');
44
- }
45
-
46
- public function getTag()
47
- {
48
- return 'with';
49
  }
50
  }
51
-
52
- class_alias('Twig_TokenParser_With', 'Twig\TokenParser\WithTokenParser', false);
1
  <?php
2
 
3
+ use Twig\TokenParser\WithTokenParser;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\WithTokenParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParser_With extends WithTokenParser
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenParserBroker.php CHANGED
@@ -10,6 +10,8 @@
10
  * file that was distributed with this source code.
11
  */
12
 
 
 
13
  /**
14
  * Default implementation of a token parser broker.
15
  *
@@ -24,9 +26,9 @@ class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface
24
  protected $brokers = [];
25
 
26
  /**
27
- * @param array|Traversable $parsers A Traversable of Twig_TokenParserInterface instances
28
- * @param array|Traversable $brokers A Traversable of Twig_TokenParserBrokerInterface instances
29
- * @param bool $triggerDeprecationError
30
  */
31
  public function __construct($parsers = [], $brokers = [], $triggerDeprecationError = true)
32
  {
@@ -35,25 +37,25 @@ class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface
35
  }
36
 
37
  foreach ($parsers as $parser) {
38
- if (!$parser instanceof Twig_TokenParserInterface) {
39
- throw new LogicException('$parsers must a an array of Twig_TokenParserInterface.');
40
  }
41
  $this->parsers[$parser->getTag()] = $parser;
42
  }
43
  foreach ($brokers as $broker) {
44
  if (!$broker instanceof Twig_TokenParserBrokerInterface) {
45
- throw new LogicException('$brokers must a an array of Twig_TokenParserBrokerInterface.');
46
  }
47
  $this->brokers[] = $broker;
48
  }
49
  }
50
 
51
- public function addTokenParser(Twig_TokenParserInterface $parser)
52
  {
53
  $this->parsers[$parser->getTag()] = $parser;
54
  }
55
 
56
- public function removeTokenParser(Twig_TokenParserInterface $parser)
57
  {
58
  $name = $parser->getTag();
59
  if (isset($this->parsers[$name]) && $parser === $this->parsers[$name]) {
@@ -80,7 +82,7 @@ class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface
80
  *
81
  * @param string $tag A tag name
82
  *
83
- * @return Twig_TokenParserInterface|null A Twig_TokenParserInterface or null if no suitable TokenParser was found
84
  */
85
  public function getTokenParser($tag)
86
  {
10
  * file that was distributed with this source code.
11
  */
12
 
13
+ use Twig\TokenParser\TokenParserInterface;
14
+
15
  /**
16
  * Default implementation of a token parser broker.
17
  *
26
  protected $brokers = [];
27
 
28
  /**
29
+ * @param array|\Traversable $parsers A \Traversable of Twig_TokenParserInterface instances
30
+ * @param array|\Traversable $brokers A \Traversable of Twig_TokenParserBrokerInterface instances
31
+ * @param bool $triggerDeprecationError
32
  */
33
  public function __construct($parsers = [], $brokers = [], $triggerDeprecationError = true)
34
  {
37
  }
38
 
39
  foreach ($parsers as $parser) {
40
+ if (!$parser instanceof TokenParserInterface) {
41
+ throw new \LogicException('$parsers must a an array of Twig_TokenParserInterface.');
42
  }
43
  $this->parsers[$parser->getTag()] = $parser;
44
  }
45
  foreach ($brokers as $broker) {
46
  if (!$broker instanceof Twig_TokenParserBrokerInterface) {
47
+ throw new \LogicException('$brokers must a an array of Twig_TokenParserBrokerInterface.');
48
  }
49
  $this->brokers[] = $broker;
50
  }
51
  }
52
 
53
+ public function addTokenParser(TokenParserInterface $parser)
54
  {
55
  $this->parsers[$parser->getTag()] = $parser;
56
  }
57
 
58
+ public function removeTokenParser(TokenParserInterface $parser)
59
  {
60
  $name = $parser->getTag();
61
  if (isset($this->parsers[$name]) && $parser === $this->parsers[$name]) {
82
  *
83
  * @param string $tag A tag name
84
  *
85
+ * @return TokenParserInterface|null A Twig_TokenParserInterface or null if no suitable TokenParser was found
86
  */
87
  public function getTokenParser($tag)
88
  {
src/lib/vendor/twig/twig/lib/Twig/TokenParserBrokerInterface.php CHANGED
@@ -10,6 +10,8 @@
10
  * file that was distributed with this source code.
11
  */
12
 
 
 
13
  /**
14
  * Interface implemented by token parser brokers.
15
  *
@@ -26,12 +28,12 @@ interface Twig_TokenParserBrokerInterface
26
  *
27
  * @param string $tag A tag name
28
  *
29
- * @return Twig_TokenParserInterface|null A Twig_TokenParserInterface or null if no suitable TokenParser was found
30
  */
31
  public function getTokenParser($tag);
32
 
33
  /**
34
- * Calls Twig_TokenParserInterface::setParser on all parsers the implementation knows of.
35
  */
36
  public function setParser(Twig_ParserInterface $parser);
37
 
10
  * file that was distributed with this source code.
11
  */
12
 
13
+ use Twig\TokenParser\TokenParserInterface;
14
+
15
  /**
16
  * Interface implemented by token parser brokers.
17
  *
28
  *
29
  * @param string $tag A tag name
30
  *
31
+ * @return TokenParserInterface|null A Twig_TokenParserInterface or null if no suitable TokenParser was found
32
  */
33
  public function getTokenParser($tag);
34
 
35
  /**
36
+ * Calls Twig\TokenParser\TokenParserInterface::setParser on all parsers the implementation knows of.
37
  */
38
  public function setParser(Twig_ParserInterface $parser);
39
 
src/lib/vendor/twig/twig/lib/Twig/TokenParserInterface.php CHANGED
@@ -1,43 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * Interface implemented by token parsers.
14
- *
15
- * @author Fabien Potencier <fabien@symfony.com>
16
- */
17
- interface Twig_TokenParserInterface
18
- {
19
- /**
20
- * Sets the parser associated with this token parser.
21
- */
22
- public function setParser(Twig_Parser $parser);
23
 
24
- /**
25
- * Parses a token and returns a node.
26
- *
27
- * @return Twig_NodeInterface
28
- *
29
- * @throws Twig_Error_Syntax
30
- */
31
- public function parse(Twig_Token $token);
32
-
33
- /**
34
- * Gets the tag name associated with this token parser.
35
- *
36
- * @return string The tag name
37
- */
38
- public function getTag();
39
  }
40
-
41
- class_alias('Twig_TokenParserInterface', 'Twig\TokenParser\TokenParserInterface', false);
42
- class_exists('Twig_Parser');
43
- class_exists('Twig_Token');
1
  <?php
2
 
3
+ use Twig\TokenParser\TokenParserInterface;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenParser\TokenParserInterface');
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenParserInterface extends TokenParserInterface
9
+ {
10
+ }
 
 
 
 
 
 
 
 
 
 
 
11
  }
 
 
 
 
src/lib/vendor/twig/twig/lib/Twig/TokenStream.php CHANGED
@@ -1,196 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- * (c) Armin Ronacher
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
- /**
14
- * Represents a token stream.
15
- *
16
- * @final
17
- *
18
- * @author Fabien Potencier <fabien@symfony.com>
19
- */
20
- class Twig_TokenStream
21
- {
22
- protected $tokens;
23
- protected $current = 0;
24
- protected $filename;
25
 
26
- private $source;
27
-
28
- /**
29
- * @param array $tokens An array of tokens
30
- * @param string|null $name The name of the template which tokens are associated with
31
- * @param string|null $source The source code associated with the tokens
32
- */
33
- public function __construct(array $tokens, $name = null, $source = null)
34
- {
35
- if (!$name instanceof Twig_Source) {
36
- if (null !== $name || null !== $source) {
37
- @trigger_error(sprintf('Passing a string as the $name argument of %s() is deprecated since version 1.27. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED);
38
- }
39
- $this->source = new Twig_Source($source, $name);
40
- } else {
41
- $this->source = $name;
42
- }
43
-
44
- $this->tokens = $tokens;
45
-
46
- // deprecated, not used anymore, to be removed in 2.0
47
- $this->filename = $this->source->getName();
48
- }
49
-
50
- public function __toString()
51
  {
52
- return implode("\n", $this->tokens);
53
- }
54
-
55
- public function injectTokens(array $tokens)
56
- {
57
- $this->tokens = array_merge(array_slice($this->tokens, 0, $this->current), $tokens, array_slice($this->tokens, $this->current));
58
- }
59
-
60
- /**
61
- * Sets the pointer to the next token and returns the old one.
62
- *
63
- * @return Twig_Token
64
- */
65
- public function next()
66
- {
67
- if (!isset($this->tokens[++$this->current])) {
68
- throw new Twig_Error_Syntax('Unexpected end of template.', $this->tokens[$this->current - 1]->getLine(), $this->source);
69
- }
70
-
71
- return $this->tokens[$this->current - 1];
72
- }
73
-
74
- /**
75
- * Tests a token, sets the pointer to the next one and returns it or throws a syntax error.
76
- *
77
- * @return Twig_Token|null The next token if the condition is true, null otherwise
78
- */
79
- public function nextIf($primary, $secondary = null)
80
- {
81
- if ($this->tokens[$this->current]->test($primary, $secondary)) {
82
- return $this->next();
83
- }
84
- }
85
-
86
- /**
87
- * Tests a token and returns it or throws a syntax error.
88
- *
89
- * @return Twig_Token
90
- */
91
- public function expect($type, $value = null, $message = null)
92
- {
93
- $token = $this->tokens[$this->current];
94
- if (!$token->test($type, $value)) {
95
- $line = $token->getLine();
96
- throw new Twig_Error_Syntax(sprintf('%sUnexpected token "%s" of value "%s" ("%s" expected%s).',
97
- $message ? $message.'. ' : '',
98
- Twig_Token::typeToEnglish($token->getType()), $token->getValue(),
99
- Twig_Token::typeToEnglish($type), $value ? sprintf(' with value "%s"', $value) : ''),
100
- $line,
101
- $this->source
102
- );
103
- }
104
- $this->next();
105
-
106
- return $token;
107
- }
108
-
109
- /**
110
- * Looks at the next token.
111
- *
112
- * @param int $number
113
- *
114
- * @return Twig_Token
115
- */
116
- public function look($number = 1)
117
- {
118
- if (!isset($this->tokens[$this->current + $number])) {
119
- throw new Twig_Error_Syntax('Unexpected end of template.', $this->tokens[$this->current + $number - 1]->getLine(), $this->source);
120
- }
121
-
122
- return $this->tokens[$this->current + $number];
123
- }
124
-
125
- /**
126
- * Tests the current token.
127
- *
128
- * @return bool
129
- */
130
- public function test($primary, $secondary = null)
131
- {
132
- return $this->tokens[$this->current]->test($primary, $secondary);
133
- }
134
-
135
- /**
136
- * Checks if end of stream was reached.
137
- *
138
- * @return bool
139
- */
140
- public function isEOF()
141
- {
142
- return Twig_Token::EOF_TYPE === $this->tokens[$this->current]->getType();
143
- }
144
-
145
- /**
146
- * @return Twig_Token
147
- */
148
- public function getCurrent()
149
- {
150
- return $this->tokens[$this->current];
151
- }
152
-
153
- /**
154
- * Gets the name associated with this stream (null if not defined).
155
- *
156
- * @return string|null
157
- *
158
- * @deprecated since 1.27 (to be removed in 2.0)
159
- */
160
- public function getFilename()
161
- {
162
- @trigger_error(sprintf('The %s() method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
163
-
164
- return $this->source->getName();
165
- }
166
-
167
- /**
168
- * Gets the source code associated with this stream.
169
- *
170
- * @return string
171
- *
172
- * @internal Don't use this as it might be empty depending on the environment configuration
173
- *
174
- * @deprecated since 1.27 (to be removed in 2.0)
175
- */
176
- public function getSource()
177
- {
178
- @trigger_error(sprintf('The %s() method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
179
-
180
- return $this->source->getCode();
181
- }
182
-
183
- /**
184
- * Gets the source associated with this stream.
185
- *
186
- * @return Twig_Source
187
- *
188
- * @internal
189
- */
190
- public function getSourceContext()
191
- {
192
- return $this->source;
193
  }
194
  }
195
-
196
- class_alias('Twig_TokenStream', 'Twig\TokenStream', false);
1
  <?php
2
 
3
+ use Twig\TokenStream;
 
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\TokenStream');
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_TokenStream extends TokenStream
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Util/DeprecationCollector.php CHANGED
@@ -1,86 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * @author Fabien Potencier <fabien@symfony.com>
14
- *
15
- * @final
16
- */
17
- class Twig_Util_DeprecationCollector
18
- {
19
- private $twig;
20
- private $deprecations;
21
 
22
- public function __construct(Twig_Environment $twig)
 
23
  {
24
- $this->twig = $twig;
25
- }
26
-
27
- /**
28
- * Returns deprecations for templates contained in a directory.
29
- *
30
- * @param string $dir A directory where templates are stored
31
- * @param string $ext Limit the loaded templates by extension
32
- *
33
- * @return array An array of deprecations
34
- */
35
- public function collectDir($dir, $ext = '.twig')
36
- {
37
- $iterator = new RegexIterator(
38
- new RecursiveIteratorIterator(
39
- new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::LEAVES_ONLY
40
- ), '{'.preg_quote($ext).'$}'
41
- );
42
-
43
- return $this->collect(new Twig_Util_TemplateDirIterator($iterator));
44
- }
45
-
46
- /**
47
- * Returns deprecations for passed templates.
48
- *
49
- * @param Traversable $iterator An iterator of templates (where keys are template names and values the contents of the template)
50
- *
51
- * @return array An array of deprecations
52
- */
53
- public function collect(Traversable $iterator)
54
- {
55
- $this->deprecations = [];
56
-
57
- set_error_handler([$this, 'errorHandler']);
58
-
59
- foreach ($iterator as $name => $contents) {
60
- try {
61
- $this->twig->parse($this->twig->tokenize(new Twig_Source($contents, $name)));
62
- } catch (Twig_Error_Syntax $e) {
63
- // ignore templates containing syntax errors
64
- }
65
- }
66
-
67
- restore_error_handler();
68
-
69
- $deprecations = $this->deprecations;
70
- $this->deprecations = [];
71
-
72
- return $deprecations;
73
- }
74
-
75
- /**
76
- * @internal
77
- */
78
- public function errorHandler($type, $msg)
79
- {
80
- if (E_USER_DEPRECATED === $type) {
81
- $this->deprecations[] = $msg;
82
- }
83
  }
84
  }
85
-
86
- class_alias('Twig_Util_DeprecationCollector', 'Twig\Util\DeprecationCollector', false);
1
  <?php
2
 
3
+ use Twig\Util\DeprecationCollector;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Util\DeprecationCollector');
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Util_DeprecationCollector extends DeprecationCollector
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/lib/Twig/Util/TemplateDirIterator.php CHANGED
@@ -1,28 +1,11 @@
1
  <?php
2
 
3
- /*
4
- * This file is part of Twig.
5
- *
6
- * (c) Fabien Potencier
7
- *
8
- * For the full copyright and license information, please view the LICENSE
9
- * file that was distributed with this source code.
10
- */
11
 
12
- /**
13
- * @author Fabien Potencier <fabien@symfony.com>
14
- */
15
- class Twig_Util_TemplateDirIterator extends IteratorIterator
16
- {
17
- public function current()
18
- {
19
- return file_get_contents(parent::current());
20
- }
21
 
22
- public function key()
 
23
  {
24
- return (string) parent::key();
25
  }
26
  }
27
-
28
- class_alias('Twig_Util_TemplateDirIterator', 'Twig\Util\TemplateDirIterator', false);
1
  <?php
2
 
3
+ use Twig\Util\TemplateDirIterator;
 
 
 
 
 
 
 
4
 
5
+ class_exists('Twig\Util\TemplateDirIterator');
 
 
 
 
 
 
 
 
6
 
7
+ if (\false) {
8
+ class Twig_Util_TemplateDirIterator extends TemplateDirIterator
9
  {
 
10
  }
11
  }
 
 
src/lib/vendor/twig/twig/src/Cache/CacheInterface.php CHANGED
@@ -1,11 +1,60 @@
1
  <?php
2
 
 
 
 
 
 
 
 
 
 
3
  namespace Twig\Cache;
4
 
5
- class_exists('Twig_CacheInterface');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- if (\false) {
8
- interface CacheInterface extends \Twig_CacheInterface
9
- {
10
- }
 
 
 
 
 
 
 
 
 
 
 
11
  }
 
 
1
  <?php
2
 
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
  namespace Twig\Cache;
13
 
14
+ /**
15
+ * Interface implemented by cache classes.
16
+ *
17
+ * It is highly recommended to always store templates on the filesystem to
18
+ * benefit from the PHP opcode cache. This interface is mostly useful if you
19
+ * need to implement a custom strategy for storing templates on the filesystem.
20
+ *
21
+ * @author Andrew Tch <andrew@noop.lv>
22
+ */
23
+ interface CacheInterface
24
+ {
25
+ /**
26
+ * Generates a cache key for the given template class name.
27
+ *
28
+ * @param string $name The template name
29
+ * @param string $className The template class name
30
+ *
31
+ * @return string
32
+ */
33
+ public function generateKey($name, $className);
34
+
35
+ /**
36
+ * Writes the compiled template to cache.
37
+ *
38
+ * @param string $key The cache key
39
+ * @param string $content The template representation as a PHP class
40
+ */
41
+ public function write($key, $content);
42
 
43
+ /**
44
+ * Loads a template from the cache.
45
+ *
46
+ * @param string $key The cache key
47
+ */
48
+ public function load($key);
49
+
50
+ /**
51
+ * Returns the modification timestamp of a key.
52
+ *
53
+ * @param string $key The cache key
54
+ *
55
+ * @return int
56
+ */
57
+ public function getTimestamp($key);
58
  }
59
+
60
+ class_alias('Twig\Cache\CacheInterface', 'Twig_CacheInterface');
src/lib/vendor/twig/twig/src/Cache/FilesystemCache.php CHANGED
@@ -1,11 +1,93 @@
1
  <?php
2
 
 
 
 
 
 
 
 
 
 
3
  namespace Twig\Cache;
4
 
5
- class_exists('Twig_Cache_Filesystem');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- if (\false) {
8
- class FilesystemCache extends \Twig_Cache_Filesystem
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
1
  <?php
2
 
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
  namespace Twig\Cache;
13
 
14
+ /**
15
+ * Implements a cache on the filesystem.
16
+ *
17
+ * @author Andrew Tch <andrew@noop.lv>
18
+ */
19
+ class FilesystemCache implements CacheInterface
20
+ {
21
+ const FORCE_BYTECODE_INVALIDATION = 1;
22
+
23
+ private $directory;
24
+ private $options;
25
+
26
+ /**
27
+ * @param string $directory The root cache directory
28
+ * @param int $options A set of options
29
+ */
30
+ public function __construct($directory, $options = 0)
31
+ {
32
+ $this->directory = rtrim($directory, '\/').'/';
33
+ $this->options = $options;
34
+ }
35
 
36
+ public function generateKey($name, $className)
 
37
  {
38
+ $hash = hash('sha256', $className);
39
+
40
+ return $this->directory.$hash[0].$hash[1].'/'.$hash.'.php';
41
+ }
42
+
43
+ public function load($key)
44
+ {
45
+ if (file_exists($key)) {
46
+ @include_once $key;
47
+ }
48
+ }
49
+
50
+ public function write($key, $content)
51
+ {
52
+ $dir = \dirname($key);
53
+ if (!is_dir($dir)) {
54
+ if (false === @mkdir($dir, 0777, true)) {
55
+ clearstatcache(true, $dir);
56
+ if (!is_dir($dir)) {
57
+ throw new \RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir));
58
+ }
59
+ }
60
+ } elseif (!is_writable($dir)) {
61
+ throw new \RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir));
62
+ }
63
+
64
+ $tmpFile = tempnam($dir, basename($key));
65
+ if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $key)) {
66
+ @chmod($key, 0666 & ~umask());
67
+
68
+ if (self::FORCE_BYTECODE_INVALIDATION == ($this->options & self::FORCE_BYTECODE_INVALIDATION)) {
69
+ // Compile cached file into bytecode cache
70
+ if (\function_exists('opcache_invalidate')) {
71
+ opcache_invalidate($key, true);
72
+ } elseif (\function_exists('apc_compile_file')) {
73
+ apc_compile_file($key);
74
+ }
75
+ }
76
+
77
+ return;
78
+ }
79
+
80
+ throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $key));
81
+ }
82
+
83
+ public function getTimestamp($key)
84
+ {
85
+ if (!file_exists($key)) {
86
+ return 0;
87
+ }
88
+
89
+ return (int) @filemtime($key);
90
  }
91
  }
92
+
93
+ class_alias('Twig\Cache\FilesystemCache', 'Twig_Cache_Filesystem');
src/lib/vendor/twig/twig/src/Cache/NullCache.php CHANGED
@@ -1,11 +1,42 @@
1
  <?php
2
 
 
 
 
 
 
 
 
 
 
3
  namespace Twig\Cache;
4
 
5
- class_exists('Twig_Cache_Null');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- if (\false) {
8
- class NullCache extends \Twig_Cache_Null
9
  {
 
10
  }
11
  }
 
 
1
  <?php
2
 
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
  namespace Twig\Cache;
13
 
14
+ /**
15
+ * Implements a no-cache strategy.
16
+ *
17
+ * @final
18
+ *
19
+ * @author Fabien Potencier <fabien@symfony.com>
20
+ */
21
+ class NullCache implements CacheInterface
22
+ {
23
+ public function generateKey($name, $className)
24
+ {
25
+ return '';
26
+ }
27
+
28
+ public function write($key, $content)
29
+ {
30
+ }
31
+
32
+ public function load($key)
33
+ {
34
+ }
35
 
36
+ public function getTimestamp($key)
 
37
  {
38
+ return 0;
39
  }
40
  }
41
+
42
+ class_alias('Twig\Cache\NullCache', 'Twig_Cache_Null');
src/lib/vendor/twig/twig/src/Compiler.php CHANGED
@@ -1,11 +1,288 @@
1
  <?php
2
 
 
 
 
 
 
 
 
 
 
 
3
  namespace Twig;
4
 
5
- class_exists('Twig_Compiler');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- if (\false) {
8
- class Compiler extends \Twig_Compiler
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
1
  <?php
2
 
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) Fabien Potencier
7
+ * (c) Armin Ronacher
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 Twig;
14
 
15
+ use Twig\Node\ModuleNode;
16
+
17
+ /**
18
+ * Compiles a node to PHP code.
19
+ *
20
+ * @author Fabien Potencier <fabien@symfony.com>
21
+ */
22
+ class Compiler implements \Twig_CompilerInterface
23
+ {
24
+ protected $lastLine;
25
+ protected $source;
26
+ protected $indentation;
27
+ protected $env;
28
+ protected $debugInfo = [];
29
+ protected $sourceOffset;
30
+ protected $sourceLine;
31
+ protected $filename;
32
+ private $varNameSalt = 0;
33
+
34
+ public function __construct(Environment $env)
35
+ {
36
+ $this->env = $env;
37
+ }
38
+
39
+ /**
40
+ * @deprecated since 1.25 (to be removed in 2.0)
41
+ */
42
+ public function getFilename()
43
+ {
44
+ @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED);
45
+
46
+ return $this->filename;
47
+ }
48
+
49
+ /**
50
+ * Returns the environment instance related to this compiler.
51
+ *
52
+ * @return Environment
53
+ */
54
+ public function getEnvironment()
55
+ {
56
+ return $this->env;
57
+ }
58
+
59
+ /**
60
+ * Gets the current PHP code after compilation.
61
+ *
62
+ * @return string The PHP code
63
+ */
64
+ public function getSource()
65
+ {
66
+ return $this->source;
67
+ }
68
+
69
+ /**
70
+ * Compiles a node.
71
+ *
72
+ * @param int $indentation The current indentation
73
+ *
74
+ * @return $this
75
+ */
76
+ public function compile(\Twig_NodeInterface $node, $indentation = 0)
77
+ {
78
+ $this->lastLine = null;
79
+ $this->source = '';
80
+ $this->debugInfo = [];
81
+ $this->sourceOffset = 0;
82
+ // source code starts at 1 (as we then increment it when we encounter new lines)
83
+ $this->sourceLine = 1;
84
+ $this->indentation = $indentation;
85
+ $this->varNameSalt = 0;
86
+
87
+ if ($node instanceof ModuleNode) {
88
+ // to be removed in 2.0
89
+ $this->filename = $node->getTemplateName();
90
+ }
91
+
92
+ $node->compile($this);
93
+
94
+ return $this;
95
+ }
96
+
97
+ public function subcompile(\Twig_NodeInterface $node, $raw = true)
98
+ {
99
+ if (false === $raw) {
100
+ $this->source .= str_repeat(' ', $this->indentation * 4);
101
+ }
102
+
103
+ $node->compile($this);
104
+
105
+ return $this;
106
+ }
107
+
108
+ /**
109
+ * Adds a raw string to the compiled code.
110
+ *
111
+ * @param string $string The string
112
+ *
113
+ * @return $this
114
+ */
115
+ public function raw($string)
116
+ {
117
+ $this->source .= $string;
118
+
119
+ return $this;
120
+ }
121
+
122
+ /**
123
+ * Writes a string to the compiled code by adding indentation.
124
+ *
125
+ * @return $this
126
+ */
127
+ public function write()
128
+ {
129
+ $strings = \func_get_args();
130
+ foreach ($strings as $string) {
131
+ $this->source .= str_repeat(' ', $this->indentation * 4).$string;
132
+ }
133
+
134
+ return $this;
135
+ }
136
+
137
+ /**
138
+ * Appends an indentation to the current PHP code after compilation.
139
+ *
140
+ * @return $this
141
+ *
142
+ * @deprecated since 1.27 (to be removed in 2.0).
143
+ */
144
+ public function addIndentation()
145
+ {
146
+ @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use write(\'\') instead.', E_USER_DEPRECATED);
147
+
148
+ $this->source .= str_repeat(' ', $this->indentation * 4);
149
+
150
+ return $this;
151
+ }
152
+
153
+ /**
154
+ * Adds a quoted string to the compiled code.
155
+ *
156
+ * @param string $value The string
157
+ *
158
+ * @return $this
159
+ */
160
+ public function string($value)
161
+ {
162
+ $this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\"));
163
+
164
+ return $this;
165
+ }
166
+
167
+ /**
168
+ * Returns a PHP representation of a given value.
169
+ *
170
+ * @param mixed $value The value to convert
171
+ *
172
+ * @return $this
173
+ */
174
+ public function repr($value)
175
+ {
176
+ if (\is_int($value) || \is_float($value)) {
177
+ if (false !== $locale = setlocale(LC_NUMERIC, '0')) {
178
+ setlocale(LC_NUMERIC, 'C');
179
+ }
180
+
181
+ $this->raw(var_export($value, true));
182
+
183
+ if (false !== $locale) {
184
+ setlocale(LC_NUMERIC, $locale);
185
+ }
186
+ } elseif (null === $value) {
187
+ $this->raw('null');
188
+ } elseif (\is_bool($value)) {
189
+ $this->raw($value ? 'true' : 'false');
190
+ } elseif (\is_array($value)) {
191
+ $this->raw('[');
192
+ $first = true;
193
+ foreach ($value as $key => $v) {
194
+ if (!$first) {
195
+ $this->raw(', ');
196
+ }
197
+ $first = false;
198
+ $this->repr($key);
199
+ $this->raw(' => ');
200
+ $this->repr($v);
201
+ }
202
+ $this->raw(']');
203
+ } else {
204
+ $this->string($value);
205
+ }
206
+
207
+ return $this;
208
+ }
209
 
210
+ /**
211
+ * Adds debugging information.
212
+ *
213
+ * @return $this
214
+ */
215
+ public function addDebugInfo(\Twig_NodeInterface $node)
216
  {
217
+ if ($node->getTemplateLine() != $this->lastLine) {
218
+ $this->write(sprintf("// line %d\n", $node->getTemplateLine()));
219
+
220
+ // when mbstring.func_overload is set to 2
221
+ // mb_substr_count() replaces substr_count()
222
+ // but they have different signatures!
223
+ if (((int) ini_get('mbstring.func_overload')) & 2) {
224
+ @trigger_error('Support for having "mbstring.func_overload" different from 0 is deprecated version 1.29 and will be removed in 2.0.', E_USER_DEPRECATED);
225
+
226
+ // this is much slower than the "right" version
227
+ $this->sourceLine += mb_substr_count(mb_substr($this->source, $this->sourceOffset), "\n");
228
+ } else {
229
+ $this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
230
+ }
231
+ $this->sourceOffset = \strlen($this->source);
232
+ $this->debugInfo[$this->sourceLine] = $node->getTemplateLine();
233
+
234
+ $this->lastLine = $node->getTemplateLine();
235
+ }
236
+
237
+ return $this;
238
+ }
239
+
240
+ public function getDebugInfo()
241
+ {
242
+ ksort($this->debugInfo);
243
+
244
+ return $this->debugInfo;
245
+ }
246
+
247
+ /**
248
+ * Indents the generated code.
249
+ *
250
+ * @param int $step The number of indentation to add
251
+ *
252
+ * @return $this
253
+ */
254
+ public function indent($step = 1)
255
+ {
256
+ $this->indentation += $step;
257
+
258
+ return $this;
259
+ }
260
+
261
+ /**
262
+ * Outdents the generated code.
263
+ *
264
+ * @param int $step The number of indentation to remove
265
+ *
266
+ * @return $this
267
+ *
268
+ * @throws \LogicException When trying to outdent too much so the indentation would become negative
269
+ */
270
+ public function outdent($step = 1)
271
+ {
272
+ // can't outdent by more steps than the current indentation level
273
+ if ($this->indentation < $step) {
274
+ throw new \LogicException('Unable to call outdent() as the indentation would become negative.');
275
+ }
276
+
277
+ $this->indentation -= $step;
278
+
279
+ return $this;
280
+ }
281
+
282
+ public function getVarName()
283
+ {
284
+ return sprintf('__internal_%s', hash('sha256', __METHOD__.$this->varNameSalt++));
285
  }
286
  }
287
+
288
+ class_alias('Twig\Compiler', 'Twig_Compiler');
src/lib/vendor/twig/twig/src/Environment.php CHANGED
@@ -1,11 +1,1647 @@
1
  <?php
2
 
 
 
 
 
 
 
 
 
 
3
  namespace Twig;
4
 
5
- class_exists('Twig_Environment');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- if (\false) {
8
- class Environment extends \Twig_Environment
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
1
  <?php
2
 
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
  namespace Twig;
13
 
14
+ use Twig\Cache\CacheInterface;
15
+ use Twig\Cache\FilesystemCache;
16
+ use Twig\Cache\NullCache;
17
+ use Twig\Error\Error;
18
+ use Twig\Error\LoaderError;
19
+ use Twig\Error\RuntimeError;
20
+ use Twig\Error\SyntaxError;
21
+ use Twig\Extension\CoreExtension;
22
+ use Twig\Extension\EscaperExtension;
23
+ use Twig\Extension\ExtensionInterface;
24
+ use Twig\Extension\GlobalsInterface;
25
+ use Twig\Extension\InitRuntimeInterface;
26
+ use Twig\Extension\OptimizerExtension;
27
+ use Twig\Extension\StagingExtension;
28
+ use Twig\Loader\ArrayLoader;
29
+ use Twig\Loader\ChainLoader;
30
+ use Twig\Loader\LoaderInterface;
31
+ use Twig\Loader\SourceContextLoaderInterface;
32
+ use Twig\Node\ModuleNode;
33
+ use Twig\NodeVisitor\NodeVisitorInterface;
34
+ use Twig\RuntimeLoader\RuntimeLoaderInterface;
35
+ use Twig\TokenParser\TokenParserInterface;
36
+
37
+ /**
38
+ * Stores the Twig configuration.
39
+ *
40
+ * @author Fabien Potencier <fabien@symfony.com>
41
+ */
42
+ class Environment
43
+ {
44
+ const VERSION = '1.38.4';
45
+ const VERSION_ID = 13804;
46
+ const MAJOR_VERSION = 2;
47
+ const MINOR_VERSION = 38;
48
+ const RELEASE_VERSION = 4;
49
+ const EXTRA_VERSION = '';
50
+
51
+ protected $charset;
52
+ protected $loader;
53
+ protected $debug;
54
+ protected $autoReload;
55
+ protected $cache;
56
+ protected $lexer;
57
+ protected $parser;
58
+ protected $compiler;
59
+ protected $baseTemplateClass;
60
+ protected $extensions;
61
+ protected $parsers;
62
+ protected $visitors;
63
+ protected $filters;
64
+ protected $tests;
65
+ protected $functions;
66
+ protected $globals;
67
+ protected $runtimeInitialized = false;
68
+ protected $extensionInitialized = false;
69
+ protected $loadedTemplates;
70
+ protected $strictVariables;
71
+ protected $unaryOperators;
72
+ protected $binaryOperators;
73
+ protected $templateClassPrefix = '__TwigTemplate_';
74
+ protected $functionCallbacks = [];
75
+ protected $filterCallbacks = [];
76
+ protected $staging;
77
+
78
+ private $originalCache;
79
+ private $bcWriteCacheFile = false;
80
+ private $bcGetCacheFilename = false;
81
+ private $lastModifiedExtension = 0;
82
+ private $extensionsByClass = [];
83
+ private $runtimeLoaders = [];
84
+ private $runtimes = [];
85
+ private $optionsHash;
86
+ private $loading = [];
87
+
88
+ /**
89
+ * Constructor.
90
+ *
91
+ * Available options:
92
+ *
93
+ * * debug: When set to true, it automatically set "auto_reload" to true as
94
+ * well (default to false).
95
+ *
96
+ * * charset: The charset used by the templates (default to UTF-8).
97
+ *
98
+ * * base_template_class: The base template class to use for generated
99
+ * templates (default to \Twig\Template).
100
+ *
101
+ * * cache: An absolute path where to store the compiled templates,
102
+ * a \Twig\Cache\CacheInterface implementation,
103
+ * or false to disable compilation cache (default).
104
+ *
105
+ * * auto_reload: Whether to reload the template if the original source changed.
106
+ * If you don't provide the auto_reload option, it will be
107
+ * determined automatically based on the debug value.
108
+ *
109
+ * * strict_variables: Whether to ignore invalid variables in templates
110
+ * (default to false).
111
+ *
112
+ * * autoescape: Whether to enable auto-escaping (default to html):
113
+ * * false: disable auto-escaping
114
+ * * true: equivalent to html
115
+ * * html, js: set the autoescaping to one of the supported strategies
116
+ * * name: set the autoescaping strategy based on the template name extension
117
+ * * PHP callback: a PHP callback that returns an escaping strategy based on the template "name"
118
+ *
119
+ * * optimizations: A flag that indicates which optimizations to apply
120
+ * (default to -1 which means that all optimizations are enabled;
121
+ * set it to 0 to disable).
122
+ */
123
+ public function __construct(LoaderInterface $loader = null, $options = [])
124
+ {
125
+ if (null !== $loader) {
126
+ $this->setLoader($loader);
127
+ } else {
128
+ @trigger_error('Not passing a "Twig\Lodaer\LoaderInterface" as the first constructor argument of "Twig\Environment" is deprecated since version 1.21.', E_USER_DEPRECATED);
129
+ }
130
+
131
+ $options = array_merge([
132
+ 'debug' => false,
133
+ 'charset' => 'UTF-8',
134
+ 'base_template_class' => '\Twig\Template',
135
+ 'strict_variables' => false,
136
+ 'autoescape' => 'html',
137
+ 'cache' => false,
138
+ 'auto_reload' => null,
139
+ 'optimizations' => -1,
140
+ ], $options);
141
+
142
+ $this->debug = (bool) $options['debug'];
143
+ $this->charset = strtoupper($options['charset']);
144
+ $this->baseTemplateClass = $options['base_template_class'];
145
+ $this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
146
+ $this->strictVariables = (bool) $options['strict_variables'];
147
+ $this->setCache($options['cache']);
148
+
149
+ $this->addExtension(new CoreExtension());
150
+ $this->addExtension(new EscaperExtension($options['autoescape']));
151
+ $this->addExtension(new OptimizerExtension($options['optimizations']));
152
+ $this->staging = new StagingExtension();
153
+
154
+ // For BC
155
+ if (\is_string($this->originalCache)) {
156
+ $r = new \ReflectionMethod($this, 'writeCacheFile');
157
+ if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
158
+ @trigger_error('The Twig\Environment::writeCacheFile method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED);
159
+
160
+ $this->bcWriteCacheFile = true;
161
+ }
162
+
163
+ $r = new \ReflectionMethod($this, 'getCacheFilename');
164
+ if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
165
+ @trigger_error('The Twig\Environment::getCacheFilename method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED);
166
+
167
+ $this->bcGetCacheFilename = true;
168
+ }
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Gets the base template class for compiled templates.
174
+ *
175
+ * @return string The base template class name
176
+ */
177
+ public function getBaseTemplateClass()
178
+ {
179
+ return $this->baseTemplateClass;
180
+ }
181
+
182
+ /**
183
+ * Sets the base template class for compiled templates.
184
+ *
185
+ * @param string $class The base template class name
186
+ */
187
+ public function setBaseTemplateClass($class)
188
+ {
189
+ $this->baseTemplateClass = $class;
190
+ $this->updateOptionsHash();
191
+ }
192
+
193
+ /**
194
+ * Enables debugging mode.
195
+ */
196
+ public function enableDebug()
197
+ {
198
+ $this->debug = true;
199
+ $this->updateOptionsHash();
200
+ }
201
+
202
+ /**
203
+ * Disables debugging mode.
204
+ */
205
+ public function disableDebug()
206
+ {
207
+ $this->debug = false;
208
+ $this->updateOptionsHash();
209
+ }
210
+
211
+ /**
212
+ * Checks if debug mode is enabled.
213
+ *
214
+ * @return bool true if debug mode is enabled, false otherwise
215
+ */
216
+ public function isDebug()
217
+ {
218
+ return $this->debug;
219
+ }
220
+
221
+ /**
222
+ * Enables the auto_reload option.
223
+ */
224
+ public function enableAutoReload()
225
+ {
226
+ $this->autoReload = true;
227
+ }
228
+
229
+ /**
230
+ * Disables the auto_reload option.
231
+ */
232
+ public function disableAutoReload()
233
+ {
234
+ $this->autoReload = false;
235
+ }
236
+
237
+ /**
238
+ * Checks if the auto_reload option is enabled.
239
+ *
240
+ * @return bool true if auto_reload is enabled, false otherwise
241
+ */
242
+ public function isAutoReload()
243
+ {
244
+ return $this->autoReload;
245
+ }
246
+
247
+ /**
248
+ * Enables the strict_variables option.
249
+ */
250
+ public function enableStrictVariables()
251
+ {
252
+ $this->strictVariables = true;
253
+ $this->updateOptionsHash();
254
+ }
255
+
256
+ /**
257
+ * Disables the strict_variables option.
258
+ */
259
+ public function disableStrictVariables()
260
+ {
261
+ $this->strictVariables = false;
262
+ $this->updateOptionsHash();
263
+ }
264
+
265
+ /**
266
+ * Checks if the strict_variables option is enabled.
267
+ *
268
+ * @return bool true if strict_variables is enabled, false otherwise
269
+ */
270
+ public function isStrictVariables()
271
+ {
272
+ return $this->strictVariables;
273
+ }
274
+
275
+ /**
276
+ * Gets the current cache implementation.
277
+ *
278
+ * @param bool $original Whether to return the original cache option or the real cache instance
279
+ *
280
+ * @return CacheInterface|string|false A Twig\Cache\CacheInterface implementation,
281
+ * an absolute path to the compiled templates,
282
+ * or false to disable cache
283
+ */
284
+ public function getCache($original = true)
285
+ {
286
+ return $original ? $this->originalCache : $this->cache;
287
+ }
288
+
289
+ /**
290
+ * Sets the current cache implementation.
291
+ *
292
+ * @param CacheInterface|string|false $cache A Twig\Cache\CacheInterface implementation,
293
+ * an absolute path to the compiled templates,
294
+ * or false to disable cache
295
+ */
296
+ public function setCache($cache)
297
+ {
298
+ if (\is_string($cache)) {
299
+ $this->originalCache = $cache;
300
+ $this->cache = new FilesystemCache($cache);
301
+ } elseif (false === $cache) {
302
+ $this->originalCache = $cache;
303
+ $this->cache = new NullCache();
304
+ } elseif (null === $cache) {
305
+ @trigger_error('Using "null" as the cache strategy is deprecated since version 1.23 and will be removed in Twig 2.0.', E_USER_DEPRECATED);
306
+ $this->originalCache = false;
307
+ $this->cache = new NullCache();
308
+ } elseif ($cache instanceof CacheInterface) {
309
+ $this->originalCache = $this->cache = $cache;
310
+ } else {
311
+ throw new \LogicException(sprintf('Cache can only be a string, false, or a \Twig\Cache\CacheInterface implementation.'));
312
+ }
313
+ }
314
+
315
+ /**
316
+ * Gets the cache filename for a given template.
317
+ *
318
+ * @param string $name The template name
319
+ *
320
+ * @return string|false The cache file name or false when caching is disabled
321
+ *
322
+ * @deprecated since 1.22 (to be removed in 2.0)
323
+ */
324
+ public function getCacheFilename($name)
325
+ {
326
+ @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
327
+
328
+ $key = $this->cache->generateKey($name, $this->getTemplateClass($name));
329
+
330
+ return !$key ? false : $key;
331
+ }
332
+
333
+ /**
334
+ * Gets the template class associated with the given string.
335
+ *
336
+ * The generated template class is based on the following parameters:
337
+ *
338
+ * * The cache key for the given template;
339
+ * * The currently enabled extensions;
340
+ * * Whether the Twig C extension is available or not;
341
+ * * PHP version;
342
+ * * Twig version;
343
+ * * Options with what environment was created.
344
+ *
345
+ * @param string $name The name for which to calculate the template class name
346
+ * @param int|null $index The index if it is an embedded template
347
+ *
348
+ * @return string The template class name
349
+ */
350
+ public function getTemplateClass($name, $index = null)
351
+ {
352
+ $key = $this->getLoader()->getCacheKey($name).$this->optionsHash;
353
+
354
+ return $this->templateClassPrefix.hash('sha256', $key).(null === $index ? '' : '___'.$index);
355
+ }
356
+
357
+ /**
358
+ * Gets the template class prefix.
359
+ *
360
+ * @return string The template class prefix
361
+ *
362
+ * @deprecated since 1.22 (to be removed in 2.0)
363
+ */
364
+ public function getTemplateClassPrefix()
365
+ {
366
+ @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
367
+
368
+ return $this->templateClassPrefix;
369
+ }
370
+
371
+ /**
372
+ * Renders a template.
373
+ *
374
+ * @param string|TemplateWrapper $name The template name
375
+ * @param array $context An array of parameters to pass to the template
376
+ *
377
+ * @return string The rendered template
378
+ *
379
+ * @throws LoaderError When the template cannot be found
380
+ * @throws SyntaxError When an error occurred during compilation
381
+ * @throws RuntimeError When an error occurred during rendering
382
+ */
383
+ public function render($name, array $context = [])
384
+ {
385
+ return $this->load($name)->render($context);
386
+ }
387
+
388
+ /**
389
+ * Displays a template.
390
+ *
391
+ * @param string|TemplateWrapper $name The template name
392
+ * @param array $context An array of parameters to pass to the template
393
+ *
394
+ * @throws LoaderError When the template cannot be found
395
+ * @throws SyntaxError When an error occurred during compilation
396
+ * @throws RuntimeError When an error occurred during rendering
397
+ */
398
+ public function display($name, array $context = [])
399
+ {
400
+ $this->load($name)->display($context);
401
+ }
402
+
403
+ /**
404
+ * Loads a template.
405
+ *
406
+ * @param string|TemplateWrapper|\Twig\Template $name The template name
407
+ *
408
+ * @throws LoaderError When the template cannot be found
409
+ * @throws RuntimeError When a previously generated cache is corrupted
410
+ * @throws SyntaxError When an error occurred during compilation
411
+ *
412
+ * @return TemplateWrapper
413
+ */
414
+ public function load($name)
415
+ {
416
+ if ($name instanceof TemplateWrapper) {
417
+ return $name;
418
+ }
419
+
420
+ if ($name instanceof Template) {
421
+ return new TemplateWrapper($this, $name);
422
+ }
423
+
424
+ return new TemplateWrapper($this, $this->loadTemplate($name));
425
+ }
426
+
427
+ /**
428
+ * Loads a template internal representation.
429
+ *
430
+ * This method is for internal use only and should never be called
431
+ * directly.
432
+ *
433
+ * @param string $name The template name
434
+ * @param int $index The index if it is an embedded template
435
+ *
436
+ * @return \Twig_TemplateInterface A template instance representing the given template name
437
+ *
438
+ * @throws LoaderError When the template cannot be found
439
+ * @throws RuntimeError When a previously generated cache is corrupted
440
+ * @throws SyntaxError When an error occurred during compilation
441
+ *
442
+ * @internal
443
+ */
444
+ public function loadTemplate($name, $index = null)
445
+ {
446
+ return $this->loadClass($this->getTemplateClass($name), $name, $index);
447
+ }
448
+
449
+ /**
450
+ * @internal
451
+ */
452
+ public function loadClass($cls, $name, $index = null)
453
+ {
454
+ $mainCls = $cls;
455
+ if (null !== $index) {
456
+ $cls .= '___'.$index;
457
+ }
458
+
459
+ if (isset($this->loadedTemplates[$cls])) {
460
+ return $this->loadedTemplates[$cls];
461
+ }
462
+
463
+ if (!class_exists($cls, false)) {
464
+ if ($this->bcGetCacheFilename) {
465
+ $key = $this->getCacheFilename($name);
466
+ } else {
467
+ $key = $this->cache->generateKey($name, $mainCls);
468
+ }
469
+
470
+ if (!$this->isAutoReload() || $this->isTemplateFresh($name, $this->cache->getTimestamp($key))) {
471
+ $this->cache->load($key);
472
+ }
473
+
474
+ if (!class_exists($cls, false)) {
475
+ $loader = $this->getLoader();
476
+ if (!$loader instanceof SourceContextLoaderInterface) {
477
+ $source = new Source($loader->getSource($name), $name);
478
+ } else {
479
+ $source = $loader->getSourceContext($name);
480
+ }
481
+
482
+ $content = $this->compileSource($source);
483
+
484
+ if ($this->bcWriteCacheFile) {
485
+ $this->writeCacheFile($key, $content);
486
+ } else {
487
+ $this->cache->write($key, $content);
488
+ $this->cache->load($key);
489
+ }
490
+
491
+ if (!class_exists($mainCls, false)) {
492
+ /* Last line of defense if either $this->bcWriteCacheFile was used,
493
+ * $this->cache is implemented as a no-op or we have a race condition
494
+ * where the cache was cleared between the above calls to write to and load from
495
+ * the cache.
496
+ */
497
+ eval('?>'.$content);
498
+ }
499
+ }
500
+
501
+ if (!class_exists($cls, false)) {
502
+ throw new RuntimeError(sprintf('Failed to load Twig template "%s", index "%s": cache might be corrupted.', $name, $index), -1, $source);
503
+ }
504
+ }
505
+
506
+ if (!$this->runtimeInitialized) {
507
+ $this->initRuntime();
508
+ }
509
 
510
+ if (isset($this->loading[$cls])) {
511
+ throw new RuntimeError(sprintf('Circular reference detected for Twig template "%s", path: %s.', $name, implode(' -> ', array_merge($this->loading, [$name]))));
512
+ }
513
+
514
+ $this->loading[$cls] = $name;
515
+
516
+ try {
517
+ $this->loadedTemplates[$cls] = new $cls($this);
518
+ unset($this->loading[$cls]);
519
+ } catch (\Exception $e) {
520
+ unset($this->loading[$cls]);
521
+
522
+ throw $e;
523
+ }
524
+
525
+ return $this->loadedTemplates[$cls];
526
+ }
527
+
528
+ /**
529
+ * Creates a template from source.
530
+ *
531
+ * This method should not be used as a generic way to load templates.
532
+ *
533
+ * @param string $template The template name
534
+ *
535
+ * @return TemplateWrapper A template instance representing the given template name
536
+ *
537
+ * @throws LoaderError When the template cannot be found
538
+ * @throws SyntaxError When an error occurred during compilation
539
+ */
540
+ public function createTemplate($template)
541
+ {
542
+ $name = sprintf('__string_template__%s', hash('sha256', $template, false));
543
+
544
+ $loader = new ChainLoader([
545
+ new ArrayLoader([$name => $template]),
546
+ $current = $this->getLoader(),
547
+ ]);
548
+
549
+ $this->setLoader($loader);
550
+ try {
551
+ $template = new TemplateWrapper($this, $this->loadTemplate($name));
552
+ } catch (\Exception $e) {
553
+ $this->setLoader($current);
554
+
555
+ throw $e;
556
+ } catch (\Throwable $e) {
557
+ $this->setLoader($current);
558
+
559
+ throw $e;
560
+ }
561
+ $this->setLoader($current);
562
+
563
+ return $template;
564
+ }
565
+
566
+ /**
567
+ * Returns true if the template is still fresh.
568
+ *
569
+ * Besides checking the loader for freshness information,
570
+ * this method also checks if the enabled extensions have
571
+ * not changed.
572
+ *
573
+ * @param string $name The template name
574
+ * @param int $time The last modification time of the cached template
575
+ *
576
+ * @return bool true if the template is fresh, false otherwise
577
+ */
578
+ public function isTemplateFresh($name, $time)
579
+ {
580
+ if (0 === $this->lastModifiedExtension) {
581
+ foreach ($this->extensions as $extension) {
582
+ $r = new \ReflectionObject($extension);
583
+ if (file_exists($r->getFileName()) && ($extensionTime = filemtime($r->getFileName())) > $this->lastModifiedExtension) {
584
+ $this->lastModifiedExtension = $extensionTime;
585
+ }
586
+ }
587
+ }
588
+
589
+ return $this->lastModifiedExtension <= $time && $this->getLoader()->isFresh($name, $time);
590
+ }
591
+
592
+ /**
593
+ * Tries to load a template consecutively from an array.
594
+ *
595
+ * Similar to load() but it also accepts instances of \Twig\Template and
596
+ * \Twig\TemplateWrapper, and an array of templates where each is tried to be loaded.
597
+ *
598
+ * @param string|Template|\Twig\TemplateWrapper|array $names A template or an array of templates to try consecutively
599
+ *
600
+ * @return TemplateWrapper|Template
601
+ *
602
+ * @throws LoaderError When none of the templates can be found
603
+ * @throws SyntaxError When an error occurred during compilation
604
+ */
605
+ public function resolveTemplate($names)
606
+ {
607
+ if (!\is_array($names)) {
608
+ $names = [$names];
609
+ }
610
+
611
+ foreach ($names as $name) {
612
+ if ($name instanceof Template) {
613
+ return $name;
614
+ }
615
+ if ($name instanceof TemplateWrapper) {
616
+ return $name;
617
+ }
618
+
619
+ try {
620
+ return $this->loadTemplate($name);
621
+ } catch (LoaderError $e) {
622
+ if (1 === \count($names)) {
623
+ throw $e;
624
+ }
625
+ }
626
+ }
627
+
628
+ throw new LoaderError(sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names)));
629
+ }
630
+
631
+ /**
632
+ * Clears the internal template cache.
633
+ *
634
+ * @deprecated since 1.18.3 (to be removed in 2.0)
635
+ */
636
+ public function clearTemplateCache()
637
+ {
638
+ @trigger_error(sprintf('The %s method is deprecated since version 1.18.3 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
639
+
640
+ $this->loadedTemplates = [];
641
+ }
642
+
643
+ /**
644
+ * Clears the template cache files on the filesystem.
645
+ *
646
+ * @deprecated since 1.22 (to be removed in 2.0)
647
+ */
648
+ public function clearCacheFiles()
649
+ {
650
+ @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
651
+
652
+ if (\is_string($this->originalCache)) {
653
+ foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->originalCache), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
654
+ if ($file->isFile()) {
655
+ @unlink($file->getPathname());
656
+ }
657
+ }
658
+ }
659
+ }
660
+
661
+ /**
662
+ * Gets the Lexer instance.
663
+ *
664
+ * @return \Twig_LexerInterface
665
+ *
666
+ * @deprecated since 1.25 (to be removed in 2.0)
667
+ */
668
+ public function getLexer()
669
  {
670
+ @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED);
671
+
672
+ if (null === $this->lexer) {
673
+ $this->lexer = new Lexer($this);
674
+ }
675
+
676
+ return $this->lexer;
677
+ }
678
+
679
+ public function setLexer(\Twig_LexerInterface $lexer)
680
+ {
681
+ $this->lexer = $lexer;
682
+ }
683
+
684
+ /**
685
+ * Tokenizes a source code.
686
+ *
687
+ * @param string|Source $source The template source code
688
+ * @param string $name The template name (deprecated)
689
+ *
690
+ * @return TokenStream
691
+ *
692
+ * @throws SyntaxError When the code is syntactically wrong
693
+ */
694
+ public function tokenize($source, $name = null)
695
+ {
696
+ if (!$source instanceof Source) {
697
+ @trigger_error(sprintf('Passing a string as the $source argument of %s() is deprecated since version 1.27. Pass a Twig\Source instance instead.', __METHOD__), E_USER_DEPRECATED);
698
+ $source = new Source($source, $name);
699
+ }
700
+
701
+ if (null === $this->lexer) {
702
+ $this->lexer = new Lexer($this);
703
+ }
704
+
705
+ return $this->lexer->tokenize($source);
706
+ }
707
+
708
+ /**
709
+ * Gets the Parser instance.
710
+ *
711
+ * @return \Twig_ParserInterface
712
+ *
713
+ * @deprecated since 1.25 (to be removed in 2.0)
714
+ */
715
+ public function getParser()
716
+ {
717
+ @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED);
718
+
719
+ if (null === $this->parser) {
720
+ $this->parser = new Parser($this);
721
+ }
722
+
723
+ return $this->parser;
724
+ }
725
+
726
+ public function setParser(\Twig_ParserInterface $parser)
727
+ {
728
+ $this->parser = $parser;
729
+ }
730
+
731
+ /**
732
+ * Converts a token stream to a node tree.
733
+ *
734
+ * @return ModuleNode
735
+ *
736
+ * @throws SyntaxError When the token stream is syntactically or semantically wrong
737
+ */
738
+ public function parse(TokenStream $stream)
739
+ {
740
+ if (null === $this->parser) {
741
+ $this->parser = new Parser($this);
742
+ }
743
+
744
+ return $this->parser->parse($stream);
745
+ }
746
+
747
+ /**
748
+ * Gets the Compiler instance.
749
+ *
750
+ * @return \Twig_CompilerInterface
751
+ *
752
+ * @deprecated since 1.25 (to be removed in 2.0)
753
+ */
754
+ public function getCompiler()
755
+ {
756
+ @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED);
757
+
758
+ if (null === $this->compiler) {
759
+ $this->compiler = new Compiler($this);
760
+ }
761
+
762
+ return $this->compiler;
763
+ }
764
+
765
+ public function setCompiler(\Twig_CompilerInterface $compiler)
766
+ {
767
+ $this->compiler = $compiler;
768
+ }
769
+
770
+ /**
771
+ * Compiles a node and returns the PHP code.
772
+ *
773
+ * @return string The compiled PHP source code
774
+ */
775
+ public function compile(\Twig_NodeInterface $node)
776
+ {
777
+ if (null === $this->compiler) {
778
+ $this->compiler = new Compiler($this);
779
+ }
780
+
781
+ return $this->compiler->compile($node)->getSource();
782
+ }
783
+
784
+ /**
785
+ * Compiles a template source code.
786
+ *
787
+ * @param string|Source $source The template source code
788
+ * @param string $name The template name (deprecated)
789
+ *
790
+ * @return string The compiled PHP source code
791
+ *
792
+ * @throws SyntaxError When there was an error during tokenizing, parsing or compiling
793
+ */
794
+ public function compileSource($source, $name = null)
795
+ {
796
+ if (!$source instanceof Source) {
797
+ @trigger_error(sprintf('Passing a string as the $source argument of %s() is deprecated since version 1.27. Pass a Twig\Source instance instead.', __METHOD__), E_USER_DEPRECATED);
798
+ $source = new Source($source, $name);
799
+ }
800
+
801
+ try {
802
+ return $this->compile($this->parse($this->tokenize($source)));
803
+ } catch (Error $e) {
804
+ $e->setSourceContext($source);
805
+ throw $e;
806
+ } catch (\Exception $e) {
807
+ throw new SyntaxError(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $source, $e);
808
+ }
809
+ }
810
+
811
+ public function setLoader(LoaderInterface $loader)
812
+ {
813
+ if (!$loader instanceof SourceContextLoaderInterface && 0 !== strpos(\get_class($loader), 'Mock_')) {
814
+ @trigger_error(sprintf('Twig loader "%s" should implement Twig\Loader\SourceContextLoaderInterface since version 1.27.', \get_class($loader)), E_USER_DEPRECATED);
815
+ }
816
+
817
+ $this->loader = $loader;
818
+ }
819
+
820
+ /**
821
+ * Gets the Loader instance.
822
+ *
823
+ * @return LoaderInterface
824
+ */
825
+ public function getLoader()
826
+ {
827
+ if (null === $this->loader) {
828
+ throw new \LogicException('You must set a loader first.');
829
+ }
830
+
831
+ return $this->loader;
832
+ }
833
+
834
+ /**
835
+ * Sets the default template charset.
836
+ *
837
+ * @param string $charset The default charset
838
+ */
839
+ public function setCharset($charset)
840
+ {
841
+ $this->charset = strtoupper($charset);
842
+ }
843
+
844
+ /**
845
+ * Gets the default template charset.
846
+ *
847
+ * @return string The default charset
848
+ */
849
+ public function getCharset()
850
+ {
851
+ return $this->charset;
852
+ }
853
+
854
+ /**
855
+ * Initializes the runtime environment.
856
+ *
857
+ * @deprecated since 1.23 (to be removed in 2.0)
858
+ */
859
+ public function initRuntime()
860
+ {
861
+ $this->runtimeInitialized = true;
862
+
863
+ foreach ($this->getExtensions() as $name => $extension) {
864
+ if (!$extension instanceof InitRuntimeInterface) {
865
+ $m = new \ReflectionMethod($extension, 'initRuntime');
866
+
867
+ $parentClass = $m->getDeclaringClass()->getName();
868
+ if ('Twig_Extension' !== $parentClass && 'Twig\Extension\AbstractExtension' !== $parentClass) {
869
+ @trigger_error(sprintf('Defining the initRuntime() method in the "%s" extension is deprecated since version 1.23. Use the `needs_environment` option to get the \Twig_Environment instance in filters, functions, or tests; or explicitly implement Twig\Extension\InitRuntimeInterface if needed (not recommended).', $name), E_USER_DEPRECATED);
870
+ }
871
+ }
872
+
873
+ $extension->initRuntime($this);
874
+ }
875
+ }
876
+
877
+ /**
878
+ * Returns true if the given extension is registered.
879
+ *
880
+ * @param string $class The extension class name
881
+ *
882
+ * @return bool Whether the extension is registered or not
883
+ */
884
+ public function hasExtension($class)
885
+ {
886
+ $class = ltrim($class, '\\');
887
+ if (!isset($this->extensionsByClass[$class]) && class_exists($class, false)) {
888
+ // For BC/FC with namespaced aliases
889
+ $class = new \ReflectionClass($class);
890
+ $class = $class->name;
891
+ }
892
+
893
+ if (isset($this->extensions[$class])) {
894
+ if ($class !== \get_class($this->extensions[$class])) {
895
+ @trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED);
896
+ }
897
+
898
+ return true;
899
+ }
900
+
901
+ return isset($this->extensionsByClass[$class]);
902
+ }
903
+
904
+ /**
905
+ * Adds a runtime loader.
906
+ */
907
+ public function addRuntimeLoader(RuntimeLoaderInterface $loader)
908
+ {
909
+ $this->runtimeLoaders[] = $loader;
910
+ }
911
+
912
+ /**
913
+ * Gets an extension by class name.
914
+ *
915
+ * @param string $class The extension class name
916
+ *
917
+ * @return ExtensionInterface
918
+ */
919
+ public function getExtension($class)
920
+ {
921
+ $class = ltrim($class, '\\');
922
+ if (!isset($this->extensionsByClass[$class]) && class_exists($class, false)) {
923
+ // For BC/FC with namespaced aliases
924
+ $class = new \ReflectionClass($class);
925
+ $class = $class->name;
926
+ }
927
+
928
+ if (isset($this->extensions[$class])) {
929
+ if ($class !== \get_class($this->extensions[$class])) {
930
+ @trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED);
931
+ }
932
+
933
+ return $this->extensions[$class];
934
+ }
935
+
936
+ if (!isset($this->extensionsByClass[$class])) {
937
+ throw new RuntimeError(sprintf('The "%s" extension is not enabled.', $class));
938
+ }
939
+
940
+ return $this->extensionsByClass[$class];
941
+ }
942
+
943
+ /**
944
+ * Returns the runtime implementation of a Twig element (filter/function/test).
945
+ *
946
+ * @param string $class A runtime class name
947
+ *
948
+ * @return object The runtime implementation
949
+ *
950
+ * @throws RuntimeError When the template cannot be found
951
+ */
952
+ public function getRuntime($class)
953
+ {
954
+ if (isset($this->runtimes[$class])) {
955
+ return $this->runtimes[$class];
956
+ }
957
+
958
+ foreach ($this->runtimeLoaders as $loader) {
959
+ if (null !== $runtime = $loader->load($class)) {
960
+ return $this->runtimes[$class] = $runtime;
961
+ }
962
+ }
963
+
964
+ throw new RuntimeError(sprintf('Unable to load the "%s" runtime.', $class));
965
+ }
966
+
967
+ public function addExtension(ExtensionInterface $extension)
968
+ {
969
+ if ($this->extensionInitialized) {
970
+ throw new \LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName()));
971
+ }
972
+
973
+ $class = \get_class($extension);
974
+ if ($class !== $extension->getName()) {
975
+ if (isset($this->extensions[$extension->getName()])) {
976
+ unset($this->extensions[$extension->getName()], $this->extensionsByClass[$class]);
977
+ @trigger_error(sprintf('The possibility to register the same extension twice ("%s") is deprecated since version 1.23 and will be removed in Twig 2.0. Use proper PHP inheritance instead.', $extension->getName()), E_USER_DEPRECATED);
978
+ }
979
+ }
980
+
981
+ $this->lastModifiedExtension = 0;
982
+ $this->extensionsByClass[$class] = $extension;
983
+ $this->extensions[$extension->getName()] = $extension;
984
+ $this->updateOptionsHash();
985
+ }
986
+
987
+ /**
988
+ * Removes an extension by name.
989
+ *
990
+ * This method is deprecated and you should not use it.
991
+ *
992
+ * @param string $name The extension name
993
+ *
994
+ * @deprecated since 1.12 (to be removed in 2.0)
995
+ */
996
+ public function removeExtension($name)
997
+ {
998
+ @trigger_error(sprintf('The %s method is deprecated since version 1.12 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
999
+
1000
+ if ($this->extensionInitialized) {
1001
+ throw new \LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name));
1002
+ }
1003
+
1004
+ $class = ltrim($name, '\\');
1005
+ if (!isset($this->extensionsByClass[$class]) && class_exists($class, false)) {
1006
+ // For BC/FC with namespaced aliases
1007
+ $class = new \ReflectionClass($class);
1008
+ $class = $class->name;
1009
+ }
1010
+
1011
+ if (isset($this->extensions[$class])) {
1012
+ if ($class !== \get_class($this->extensions[$class])) {
1013
+ @trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED);
1014
+ }
1015
+
1016
+ unset($this->extensions[$class]);
1017
+ }
1018
+
1019
+ unset($this->extensions[$class]);
1020
+ $this->updateOptionsHash();
1021
+ }
1022
+
1023
+ /**
1024
+ * Registers an array of extensions.
1025
+ *
1026
+ * @param array $extensions An array of extensions
1027
+ */
1028
+ public function setExtensions(array $extensions)
1029
+ {
1030
+ foreach ($extensions as $extension) {
1031
+ $this->addExtension($extension);
1032
+ }
1033
+ }
1034
+
1035
+ /**
1036
+ * Returns all registered extensions.
1037
+ *
1038
+ * @return ExtensionInterface[] An array of extensions (keys are for internal usage only and should not be relied on)
1039
+ */
1040
+ public function getExtensions()
1041
+ {
1042
+ return $this->extensions;
1043
+ }
1044
+
1045
+ public function addTokenParser(TokenParserInterface $parser)
1046
+ {
1047
+ if ($this->extensionInitialized) {
1048
+ throw new \LogicException('Unable to add a token parser as extensions have already been initialized.');
1049
+ }
1050
+
1051
+ $this->staging->addTokenParser($parser);
1052
+ }
1053
+
1054
+ /**
1055
+ * Gets the registered Token Parsers.
1056
+ *
1057
+ * @return \Twig_TokenParserBrokerInterface
1058
+ *
1059
+ * @internal
1060
+ */
1061
+ public function getTokenParsers()
1062
+ {
1063
+ if (!$this->extensionInitialized) {
1064
+ $this->initExtensions();
1065
+ }
1066
+
1067
+ return $this->parsers;
1068
+ }
1069
+
1070
+ /**
1071
+ * Gets registered tags.
1072
+ *
1073
+ * Be warned that this method cannot return tags defined by \Twig_TokenParserBrokerInterface classes.
1074
+ *
1075
+ * @return TokenParserInterface[]
1076
+ *
1077
+ * @internal
1078
+ */
1079
+ public function getTags()
1080
+ {
1081
+ $tags = [];
1082
+ foreach ($this->getTokenParsers()->getParsers() as $parser) {
1083
+ if ($parser instanceof TokenParserInterface) {
1084
+ $tags[$parser->getTag()] = $parser;
1085
+ }
1086
+ }
1087
+
1088
+ return $tags;
1089
+ }
1090
+
1091
+ public function addNodeVisitor(NodeVisitorInterface $visitor)
1092
+ {
1093
+ if ($this->extensionInitialized) {
1094
+ throw new \LogicException('Unable to add a node visitor as extensions have already been initialized.');
1095
+ }
1096
+
1097
+ $this->staging->addNodeVisitor($visitor);
1098
+ }
1099
+
1100
+ /**
1101
+ * Gets the registered Node Visitors.
1102
+ *
1103
+ * @return NodeVisitorInterface[]
1104
+ *
1105
+ * @internal
1106
+ */
1107
+ public function getNodeVisitors()
1108
+ {
1109
+ if (!$this->extensionInitialized) {
1110
+ $this->initExtensions();
1111
+ }
1112
+
1113
+ return $this->visitors;
1114
+ }
1115
+
1116
+ /**
1117
+ * Registers a Filter.
1118
+ *
1119
+ * @param string|TwigFilter $name The filter name or a \Twig_SimpleFilter instance
1120
+ * @param \Twig_FilterInterface|TwigFilter $filter
1121
+ */
1122
+ public function addFilter($name, $filter = null)
1123
+ {
1124
+ if (!$name instanceof TwigFilter && !($filter instanceof TwigFilter || $filter instanceof \Twig_FilterInterface)) {
1125
+ throw new \LogicException('A filter must be an instance of \Twig_FilterInterface or \Twig_SimpleFilter.');
1126
+ }
1127
+
1128
+ if ($name instanceof TwigFilter) {
1129
+ $filter = $name;
1130
+ $name = $filter->getName();
1131
+ } else {
1132
+ @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleFilter" instead when defining filter "%s".', __METHOD__, $name), E_USER_DEPRECATED);
1133
+ }
1134
+
1135
+ if ($this->extensionInitialized) {
1136
+ throw new \LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name));
1137
+ }
1138
+
1139
+ $this->staging->addFilter($name, $filter);
1140
+ }
1141
+
1142
+ /**
1143
+ * Get a filter by name.
1144
+ *
1145
+ * Subclasses may override this method and load filters differently;
1146
+ * so no list of filters is available.
1147
+ *
1148
+ * @param string $name The filter name
1149
+ *
1150
+ * @return \Twig_Filter|false
1151
+ *
1152
+ * @internal
1153
+ */
1154
+ public function getFilter($name)
1155
+ {
1156
+ if (!$this->extensionInitialized) {
1157
+ $this->initExtensions();
1158
+ }
1159
+
1160
+ if (isset($this->filters[$name])) {
1161
+ return $this->filters[$name];
1162
+ }
1163
+
1164
+ foreach ($this->filters as $pattern => $filter) {
1165
+ $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
1166
+
1167
+ if ($count) {
1168
+ if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
1169
+ array_shift($matches);
1170
+ $filter->setArguments($matches);
1171
+
1172
+ return $filter;
1173
+ }
1174
+ }
1175
+ }
1176
+
1177
+ foreach ($this->filterCallbacks as $callback) {
1178
+ if (false !== $filter = \call_user_func($callback, $name)) {
1179
+ return $filter;
1180
+ }
1181
+ }
1182
+
1183
+ return false;
1184
+ }
1185
+
1186
+ public function registerUndefinedFilterCallback($callable)
1187
+ {
1188
+ $this->filterCallbacks[] = $callable;
1189
+ }
1190
+
1191
+ /**
1192
+ * Gets the registered Filters.
1193
+ *
1194
+ * Be warned that this method cannot return filters defined with registerUndefinedFilterCallback.
1195
+ *
1196
+ * @return \Twig_FilterInterface[]
1197
+ *
1198
+ * @see registerUndefinedFilterCallback
1199
+ *
1200
+ * @internal
1201
+ */
1202
+ public function getFilters()
1203
+ {
1204
+ if (!$this->extensionInitialized) {
1205
+ $this->initExtensions();
1206
+ }
1207
+
1208
+ return $this->filters;
1209
+ }
1210
+
1211
+ /**
1212
+ * Registers a Test.
1213
+ *
1214
+ * @param string|TwigTest $name The test name or a \Twig_SimpleTest instance
1215
+ * @param \Twig_TestInterface|TwigTest $test A \Twig_TestInterface instance or a \Twig_SimpleTest instance
1216
+ */
1217
+ public function addTest($name, $test = null)
1218
+ {
1219
+ if (!$name instanceof TwigTest && !($test instanceof TwigTest || $test instanceof \Twig_TestInterface)) {
1220
+ throw new \LogicException('A test must be an instance of \Twig_TestInterface or \Twig_SimpleTest.');
1221
+ }
1222
+
1223
+ if ($name instanceof TwigTest) {
1224
+ $test = $name;
1225
+ $name = $test->getName();
1226
+ } else {
1227
+ @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleTest" instead when defining test "%s".', __METHOD__, $name), E_USER_DEPRECATED);
1228
+ }
1229
+
1230
+ if ($this->extensionInitialized) {
1231
+ throw new \LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name));
1232
+ }
1233
+
1234
+ $this->staging->addTest($name, $test);
1235
+ }
1236
+
1237
+ /**
1238
+ * Gets the registered Tests.
1239
+ *
1240
+ * @return \Twig_TestInterface[]
1241
+ *
1242
+ * @internal
1243
+ */
1244
+ public function getTests()
1245
+ {
1246
+ if (!$this->extensionInitialized) {
1247
+ $this->initExtensions();
1248
+ }
1249
+
1250
+ return $this->tests;
1251
+ }
1252
+
1253
+ /**
1254
+ * Gets a test by name.
1255
+ *
1256
+ * @param string $name The test name
1257
+ *
1258
+ * @return \Twig_Test|false
1259
+ *
1260
+ * @internal
1261
+ */
1262
+ public function getTest($name)
1263
+ {
1264
+ if (!$this->extensionInitialized) {
1265
+ $this->initExtensions();
1266
+ }
1267
+
1268
+ if (isset($this->tests[$name])) {
1269
+ return $this->tests[$name];
1270
+ }
1271
+
1272
+ foreach ($this->tests as $pattern => $test) {
1273
+ $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
1274
+
1275
+ if ($count) {
1276
+ if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
1277
+ array_shift($matches);
1278
+ $test->setArguments($matches);
1279
+
1280
+ return $test;
1281
+ }
1282
+ }
1283
+ }
1284
+
1285
+ return false;
1286
+ }
1287
+
1288
+ /**
1289
+ * Registers a Function.
1290
+ *
1291
+ * @param string|TwigFunction $name The function name or a \Twig_SimpleFunction instance
1292
+ * @param \Twig_FunctionInterface|TwigFunction $function
1293
+ */
1294
+ public function addFunction($name, $function = null)
1295
+ {
1296
+ if (!$name instanceof TwigFunction && !($function instanceof TwigFunction || $function instanceof \Twig_FunctionInterface)) {
1297
+ throw new \LogicException('A function must be an instance of \Twig_FunctionInterface or \Twig_SimpleFunction.');
1298
+ }
1299
+
1300
+ if ($name instanceof TwigFunction) {
1301
+ $function = $name;
1302
+ $name = $function->getName();
1303
+ } else {
1304
+ @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleFunction" instead when defining function "%s".', __METHOD__, $name), E_USER_DEPRECATED);
1305
+ }
1306
+
1307
+ if ($this->extensionInitialized) {
1308
+ throw new \LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name));
1309
+ }
1310
+
1311
+ $this->staging->addFunction($name, $function);
1312
+ }
1313
+
1314
+ /**
1315
+ * Get a function by name.
1316
+ *
1317
+ * Subclasses may override this method and load functions differently;
1318
+ * so no list of functions is available.
1319
+ *
1320
+ * @param string $name function name
1321
+ *
1322
+ * @return \Twig_Function|false
1323
+ *
1324
+ * @internal
1325
+ */
1326
+ public function getFunction($name)
1327
+ {
1328
+ if (!$this->extensionInitialized) {
1329
+ $this->initExtensions();
1330
+ }
1331
+
1332
+ if (isset($this->functions[$name])) {
1333
+ return $this->functions[$name];
1334
+ }
1335
+
1336
+ foreach ($this->functions as $pattern => $function) {
1337
+ $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count);
1338
+
1339
+ if ($count) {
1340
+ if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
1341
+ array_shift($matches);
1342
+ $function->setArguments($matches);
1343
+
1344
+ return $function;
1345
+ }
1346
+ }
1347
+ }
1348
+
1349
+ foreach ($this->functionCallbacks as $callback) {
1350
+ if (false !== $function = \call_user_func($callback, $name)) {
1351
+ return $function;
1352
+ }
1353
+ }
1354
+
1355
+ return false;
1356
+ }
1357
+
1358
+ public function registerUndefinedFunctionCallback($callable)
1359
+ {
1360
+ $this->functionCallbacks[] = $callable;
1361
+ }
1362
+
1363
+ /**
1364
+ * Gets registered functions.
1365
+ *
1366
+ * Be warned that this method cannot return functions defined with registerUndefinedFunctionCallback.
1367
+ *
1368
+ * @return \Twig_FunctionInterface[]
1369
+ *
1370
+ * @see registerUndefinedFunctionCallback
1371
+ *
1372
+ * @internal
1373
+ */
1374
+ public function getFunctions()
1375
+ {
1376
+ if (!$this->extensionInitialized) {
1377
+ $this->initExtensions();
1378
+ }
1379
+
1380
+ return $this->functions;
1381
+ }
1382
+
1383
+ /**
1384
+ * Registers a Global.
1385
+ *
1386
+ * New globals can be added before compiling or rendering a template;
1387
+ * but after, you can only update existing globals.
1388
+ *
1389
+ * @param string $name The global name
1390
+ * @param mixed $value The global value
1391
+ */
1392
+ public function addGlobal($name, $value)
1393
+ {
1394
+ if ($this->extensionInitialized || $this->runtimeInitialized) {
1395
+ if (null === $this->globals) {
1396
+ $this->globals = $this->initGlobals();
1397
+ }
1398
+
1399
+ if (!\array_key_exists($name, $this->globals)) {
1400
+ // The deprecation notice must be turned into the following exception in Twig 2.0
1401
+ @trigger_error(sprintf('Registering global variable "%s" at runtime or when the extensions have already been initialized is deprecated since version 1.21.', $name), E_USER_DEPRECATED);
1402
+ //throw new \LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name));
1403
+ }
1404
+ }
1405
+
1406
+ if ($this->extensionInitialized || $this->runtimeInitialized) {
1407
+ // update the value
1408
+ $this->globals[$name] = $value;
1409
+ } else {
1410
+ $this->staging->addGlobal($name, $value);
1411
+ }
1412
+ }
1413
+
1414
+ /**
1415
+ * Gets the registered Globals.
1416
+ *
1417
+ * @return array An array of globals
1418
+ *
1419
+ * @internal
1420
+ */
1421
+ public function getGlobals()
1422
+ {
1423
+ if (!$this->runtimeInitialized && !$this->extensionInitialized) {
1424
+ return $this->initGlobals();
1425
+ }
1426
+
1427
+ if (null === $this->globals) {
1428
+ $this->globals = $this->initGlobals();
1429
+ }
1430
+
1431
+ return $this->globals;
1432
+ }
1433
+
1434
+ /**
1435
+ * Merges a context with the defined globals.
1436
+ *
1437
+ * @param array $context An array representing the context
1438
+ *
1439
+ * @return array The context merged with the globals
1440
+ */
1441
+ public function mergeGlobals(array $context)
1442
+ {
1443
+ // we don't use array_merge as the context being generally
1444
+ // bigger than globals, this code is faster.
1445
+ foreach ($this->getGlobals() as $key => $value) {
1446
+ if (!\array_key_exists($key, $context)) {
1447
+ $context[$key] = $value;
1448
+ }
1449
+ }
1450
+
1451
+ return $context;
1452
+ }
1453
+
1454
+ /**
1455
+ * Gets the registered unary Operators.
1456
+ *
1457
+ * @return array An array of unary operators
1458
+ *
1459
+ * @internal
1460
+ */
1461
+ public function getUnaryOperators()
1462
+ {
1463
+ if (!$this->extensionInitialized) {
1464
+ $this->initExtensions();
1465
+ }
1466
+
1467
+ return $this->unaryOperators;
1468
+ }
1469
+
1470
+ /**
1471
+ * Gets the registered binary Operators.
1472
+ *
1473
+ * @return array An array of binary operators
1474
+ *
1475
+ * @internal
1476
+ */
1477
+ public function getBinaryOperators()
1478
+ {
1479
+ if (!$this->extensionInitialized) {
1480
+ $this->initExtensions();
1481
+ }
1482
+
1483
+ return $this->binaryOperators;
1484
+ }
1485
+
1486
+ /**
1487
+ * @deprecated since 1.23 (to be removed in 2.0)
1488
+ */
1489
+ public function computeAlternatives($name, $items)
1490
+ {
1491
+ @trigger_error(sprintf('The %s method is deprecated since version 1.23 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
1492
+
1493
+ return SyntaxError::computeAlternatives($name, $items);
1494
+ }
1495
+
1496
+ /**
1497
+ * @internal
1498
+ */
1499
+ protected function initGlobals()
1500
+ {
1501
+ $globals = [];
1502
+ foreach ($this->extensions as $name => $extension) {
1503
+ if (!$extension instanceof GlobalsInterface) {
1504
+ $m = new \ReflectionMethod($extension, 'getGlobals');
1505
+
1506
+ $parentClass = $m->getDeclaringClass()->getName();
1507
+ if ('Twig_Extension' !== $parentClass && 'Twig\Extension\AbstractExtension' !== $parentClass) {
1508
+ @trigger_error(sprintf('Defining the getGlobals() method in the "%s" extension without explicitly implementing Twig\Extension\GlobalsInterface is deprecated since version 1.23.', $name), E_USER_DEPRECATED);
1509
+ }
1510
+ }
1511
+
1512
+ $extGlob = $extension->getGlobals();
1513
+ if (!\is_array($extGlob)) {
1514
+ throw new \UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', \get_class($extension)));
1515
+ }
1516
+
1517
+ $globals[] = $extGlob;
1518
+ }
1519
+
1520
+ $globals[] = $this->staging->getGlobals();
1521
+
1522
+ return \call_user_func_array('array_merge', $globals);
1523
+ }
1524
+
1525
+ /**
1526
+ * @internal
1527
+ */
1528
+ protected function initExtensions()
1529
+ {
1530
+ if ($this->extensionInitialized) {
1531
+ return;
1532
+ }
1533
+
1534
+ $this->parsers = new \Twig_TokenParserBroker([], [], false);
1535
+ $this->filters = [];
1536
+ $this->functions = [];
1537
+ $this->tests = [];
1538
+ $this->visitors = [];
1539
+ $this->unaryOperators = [];
1540
+ $this->binaryOperators = [];
1541
+
1542
+ foreach ($this->extensions as $extension) {
1543
+ $this->initExtension($extension);
1544
+ }
1545
+ $this->initExtension($this->staging);
1546
+ // Done at the end only, so that an exception during initialization does not mark the environment as initialized when catching the exception
1547
+ $this->extensionInitialized = true;
1548
+ }
1549
+
1550
+ /**
1551
+ * @internal
1552
+ */
1553
+ protected function initExtension(ExtensionInterface $extension)
1554
+ {
1555
+ // filters
1556
+ foreach ($extension->getFilters() as $name => $filter) {
1557
+ if ($filter instanceof TwigFilter) {
1558
+ $name = $filter->getName();
1559
+ } else {
1560
+ @trigger_error(sprintf('Using an instance of "%s" for filter "%s" is deprecated since version 1.21. Use \Twig_SimpleFilter instead.', \get_class($filter), $name), E_USER_DEPRECATED);
1561
+ }
1562
+
1563
+ $this->filters[$name] = $filter;
1564
+ }
1565
+
1566
+ // functions
1567
+ foreach ($extension->getFunctions() as $name => $function) {
1568
+ if ($function instanceof TwigFunction) {
1569
+ $name = $function->getName();
1570
+ } else {
1571
+ @trigger_error(sprintf('Using an instance of "%s" for function "%s" is deprecated since version 1.21. Use \Twig_SimpleFunction instead.', \get_class($function), $name), E_USER_DEPRECATED);
1572
+ }
1573
+
1574
+ $this->functions[$name] = $function;
1575
+ }
1576
+
1577
+ // tests
1578
+ foreach ($extension->getTests() as $name => $test) {
1579
+ if ($test instanceof TwigTest) {
1580
+ $name = $test->getName();
1581
+ } else {
1582
+ @trigger_error(sprintf('Using an instance of "%s" for test "%s" is deprecated since version 1.21. Use \Twig_SimpleTest instead.', \get_class($test), $name), E_USER_DEPRECATED);
1583
+ }
1584
+
1585
+ $this->tests[$name] = $test;
1586
+ }
1587
+
1588
+ // token parsers
1589
+ foreach ($extension->getTokenParsers() as $parser) {
1590
+ if ($parser instanceof TokenParserInterface) {
1591
+ $this->parsers->addTokenParser($parser);
1592
+ } elseif ($parser instanceof \Twig_TokenParserBrokerInterface) {
1593
+ @trigger_error('Registering a \Twig_TokenParserBrokerInterface instance is deprecated since version 1.21.', E_USER_DEPRECATED);
1594
+
1595
+ $this->parsers->addTokenParserBroker($parser);
1596
+ } else {
1597
+ throw new \LogicException('getTokenParsers() must return an array of \Twig_TokenParserInterface or \Twig_TokenParserBrokerInterface instances.');
1598
+ }
1599
+ }
1600
+
1601
+ // node visitors
1602
+ foreach ($extension->getNodeVisitors() as $visitor) {
1603
+ $this->visitors[] = $visitor;
1604
+ }
1605
+
1606
+ // operators
1607
+ if ($operators = $extension->getOperators()) {
1608
+ if (!\is_array($operators)) {
1609
+ throw new \InvalidArgumentException(sprintf('"%s::getOperators()" must return an array with operators, got "%s".', \get_class($extension), \is_object($operators) ? \get_class($operators) : \gettype($operators).(\is_resource($operators) ? '' : '#'.$operators)));
1610
+ }
1611
+
1612
+ if (2 !== \count($operators)) {
1613
+ throw new \InvalidArgumentException(sprintf('"%s::getOperators()" must return an array of 2 elements, got %d.', \get_class($extension), \count($operators)));
1614
+ }
1615
+
1616
+ $this->unaryOperators = array_merge($this->unaryOperators, $operators[0]);
1617
+ $this->binaryOperators = array_merge($this->binaryOperators, $operators[1]);
1618
+ }
1619
+ }
1620
+
1621
+ /**
1622
+ * @deprecated since 1.22 (to be removed in 2.0)
1623
+ */
1624
+ protected function writeCacheFile($file, $content)
1625
+ {
1626
+ $this->cache->write($file, $content);
1627
+ }
1628
+
1629
+ private function updateOptionsHash()
1630
+ {
1631
+ $hashParts = array_merge(
1632
+ array_keys($this->extensions),
1633
+ [
1634
+ (int) \function_exists('twig_template_get_attributes'),
1635
+ PHP_MAJOR_VERSION,
1636
+ PHP_MINOR_VERSION,
1637
+ self::VERSION,
1638
+ (int) $this->debug,
1639
+ $this->baseTemplateClass,
1640
+ (int) $this->strictVariables,
1641
+ ]
1642
+ );
1643
+ $this->optionsHash = implode(':', $hashParts);
1644
  }
1645
  }
1646
+
1647
+ class_alias('Twig\Environment', 'Twig_Environment');
src/lib/vendor/twig/twig/src/Error/Error.php CHANGED
@@ -1,11 +1,337 @@
1
  <?php
2
 
 
 
 
 
 
 
 
 
 
3
  namespace Twig\Error;
4
 
5
- class_exists('Twig_Error');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- if (\false) {
8
- class Error extends \Twig_Error
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
1
  <?php
2
 
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
  namespace Twig\Error;
13
 
14
+ use Twig\Source;
15
+ use Twig\Template;
16
+
17
+ /**
18
+ * Twig base exception.
19
+ *
20
+ * This exception class and its children must only be used when
21
+ * an error occurs during the loading of a template, when a syntax error
22
+ * is detected in a template, or when rendering a template. Other
23
+ * errors must use regular PHP exception classes (like when the template
24
+ * cache directory is not writable for instance).
25
+ *
26
+ * To help debugging template issues, this class tracks the original template
27
+ * name and line where the error occurred.
28
+ *
29
+ * Whenever possible, you must set these information (original template name
30
+ * and line number) yourself by passing them to the constructor. If some or all
31
+ * these information are not available from where you throw the exception, then
32
+ * this class will guess them automatically (when the line number is set to -1
33
+ * and/or the name is set to null). As this is a costly operation, this
34
+ * can be disabled by passing false for both the name and the line number
35
+ * when creating a new instance of this class.
36
+ *
37
+ * @author Fabien Potencier <fabien@symfony.com>
38
+ */
39
+ class Error extends \Exception
40
+ {
41
+ protected $lineno;
42
+ // to be renamed to name in 2.0
43
+ protected $filename;
44
+ protected $rawMessage;
45
+
46
+ private $sourcePath;
47
+ private $sourceCode;
48
+
49
+ /**
50
+ * Constructor.
51
+ *
52
+ * Set both the line number and the name to false to
53
+ * disable automatic guessing of the original template name
54
+ * and line number.
55
+ *
56
+ * Set the line number to -1 to enable its automatic guessing.
57
+ * Set the name to null to enable its automatic guessing.
58
+ *
59
+ * By default, automatic guessing is enabled.
60
+ *
61
+ * @param string $message The error message
62
+ * @param int $lineno The template line where the error occurred
63
+ * @param Source|string|null $source The source context where the error occurred
64
+ * @param \Exception $previous The previous exception
65
+ */
66
+ public function __construct($message, $lineno = -1, $source = null, \Exception $previous = null, $autoGuess = true)
67
+ {
68
+ if (null === $source) {
69
+ $name = null;
70
+ } elseif (!$source instanceof Source) {
71
+ // for compat with the Twig C ext., passing the template name as string is accepted
72
+ $name = $source;
73
+ } else {
74
+ $name = $source->getName();
75
+ $this->sourceCode = $source->getCode();
76
+ $this->sourcePath = $source->getPath();
77
+ }
78
+ parent::__construct('', 0, $previous);
79
+
80
+ $this->lineno = $lineno;
81
+ $this->filename = $name;
82
+
83
+ if ($autoGuess && (-1 === $lineno || null === $name || null === $this->sourcePath)) {
84
+ $this->guessTemplateInfo();
85
+ }
86
+
87
+ $this->rawMessage = $message;
88
+
89
+ $this->updateRepr();
90
+ }
91
 
92
+ /**
93
+ * Gets the raw message.
94
+ *
95
+ * @return string The raw message
96
+ */
97
+ public function getRawMessage()
98
  {
99
+ return $this->rawMessage;
100
+ }
101
+
102
+ /**
103
+ * Gets the logical name where the error occurred.
104
+ *
105
+ * @return string The name
106
+ *
107
+ * @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead.
108
+ */
109
+ public function getTemplateFile()
110
+ {
111
+ @trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
112
+
113
+ return $this->filename;
114
+ }
115
+
116
+ /**
117
+ * Sets the logical name where the error occurred.
118
+ *
119
+ * @param string $name The name
120
+ *
121
+ * @deprecated since 1.27 (to be removed in 2.0). Use setSourceContext() instead.
122
+ */
123
+ public function setTemplateFile($name)
124
+ {
125
+ @trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use setSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
126
+
127
+ $this->filename = $name;
128
+
129
+ $this->updateRepr();
130
+ }
131
+
132
+ /**
133
+ * Gets the logical name where the error occurred.
134
+ *
135
+ * @return string The name
136
+ *
137
+ * @deprecated since 1.29 (to be removed in 2.0). Use getSourceContext() instead.
138
+ */
139
+ public function getTemplateName()
140
+ {
141
+ @trigger_error(sprintf('The "%s" method is deprecated since version 1.29 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
142
+
143
+ return $this->filename;
144
+ }
145
+
146
+ /**
147
+ * Sets the logical name where the error occurred.
148
+ *
149
+ * @param string $name The name
150
+ *
151
+ * @deprecated since 1.29 (to be removed in 2.0). Use setSourceContext() instead.
152
+ */
153
+ public function setTemplateName($name)
154
+ {
155
+ @trigger_error(sprintf('The "%s" method is deprecated since version 1.29 and will be removed in 2.0. Use setSourceContext() instead.', __METHOD__), E_USER_DEPRECATED);
156
+
157
+ $this->filename = $name;
158
+ $this->sourceCode = $this->sourcePath = null;
159
+
160
+ $this->updateRepr();
161
+ }
162
+
163
+ /**
164
+ * Gets the template line where the error occurred.
165
+ *
166
+ * @return int The template line
167
+ */
168
+ public function getTemplateLine()
169
+ {
170
+ return $this->lineno;
171
+ }
172
+
173
+ /**
174
+ * Sets the template line where the error occurred.
175
+ *
176
+ * @param int $lineno The template line
177
+ */
178
+ public function setTemplateLine($lineno)
179
+ {
180
+ $this->lineno = $lineno;
181
+
182
+ $this->updateRepr();
183
+ }
184
+
185
+ /**
186
+ * Gets the source context of the Twig template where the error occurred.
187
+ *
188
+ * @return Source|null
189
+ */
190
+ public function getSourceContext()
191
+ {
192
+ return $this->filename ? new Source($this->sourceCode, $this->filename, $this->sourcePath) : null;
193
+ }
194
+
195
+ /**
196
+ * Sets the source context of the Twig template where the error occurred.
197
+ */
198
+ public function setSourceContext(Source $source = null)
199
+ {
200
+ if (null === $source) {
201
+ $this->sourceCode = $this->filename = $this->sourcePath = null;
202
+ } else {
203
+ $this->sourceCode = $source->getCode();
204
+ $this->filename = $source->getName();
205
+ $this->sourcePath = $source->getPath();
206
+ }
207
+
208
+ $this->updateRepr();
209
+ }
210
+
211
+ public function guess()
212
+ {
213
+ $this->guessTemplateInfo();
214
+ $this->updateRepr();
215
+ }
216
+
217
+ public function appendMessage($rawMessage)
218
+ {
219
+ $this->rawMessage .= $rawMessage;
220
+ $this->updateRepr();
221
+ }
222
+
223
+ /**
224
+ * @internal
225
+ */
226
+ protected function updateRepr()
227
+ {
228
+ $this->message = $this->rawMessage;
229
+
230
+ if ($this->sourcePath && $this->lineno > 0) {
231
+ $this->file = $this->sourcePath;
232
+ $this->line = $this->lineno;
233
+
234
+ return;
235
+ }
236
+
237
+ $dot = false;
238
+ if ('.' === substr($this->message, -1)) {
239
+ $this->message = substr($this->message, 0, -1);
240
+ $dot = true;
241
+ }
242
+
243
+ $questionMark = false;
244
+ if ('?' === substr($this->message, -1)) {
245
+ $this->message = substr($this->message, 0, -1);
246
+ $questionMark = true;
247
+ }
248
+
249
+ if ($this->filename) {
250
+ if (\is_string($this->filename) || (\is_object($this->filename) && method_exists($this->filename, '__toString'))) {
251
+ $name = sprintf('"%s"', $this->filename);
252
+ } else {
253
+ $name = json_encode($this->filename);
254
+ }
255
+ $this->message .= sprintf(' in %s', $name);
256
+ }
257
+
258
+ if ($this->lineno && $this->lineno >= 0) {
259
+ $this->message .= sprintf(' at line %d', $this->lineno);
260
+ }
261
+
262
+ if ($dot) {
263
+ $this->message .= '.';
264
+ }
265
+
266
+ if ($questionMark) {
267
+ $this->message .= '?';
268
+ }
269
+ }
270
+
271
+ /**
272
+ * @internal
273
+ */
274
+ protected function guessTemplateInfo()
275
+ {
276
+ $template = null;
277
+ $templateClass = null;
278
+
279
+ $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT);
280
+ foreach ($backtrace as $trace) {
281
+ if (isset($trace['object']) && $trace['object'] instanceof Template && 'Twig_Template' !== \get_class($trace['object'])) {
282
+ $currentClass = \get_class($trace['object']);
283
+ $isEmbedContainer = 0 === strpos($templateClass, $currentClass);
284
+ if (null === $this->filename || ($this->filename == $trace['object']->getTemplateName() && !$isEmbedContainer)) {
285
+ $template = $trace['object'];
286
+ $templateClass = \get_class($trace['object']);
287
+ }
288
+ }
289
+ }
290
+
291
+ // update template name
292
+ if (null !== $template && null === $this->filename) {
293
+ $this->filename = $template->getTemplateName();
294
+ }
295
+
296
+ // update template path if any
297
+ if (null !== $template && null === $this->sourcePath) {
298
+ $src = $template->getSourceContext();
299
+ $this->sourceCode = $src->getCode();
300
+ $this->sourcePath = $src->getPath();
301
+ }
302
+
303
+ if (null === $template || $this->lineno > -1) {
304
+ return;
305
+ }
306
+
307
+ $r = new \ReflectionObject($template);
308
+ $file = $r->getFileName();
309
+
310
+ $exceptions = [$e = $this];
311
+ while ($e instanceof self && $e = $e->getPrevious()) {
312
+ $exceptions[] = $e;
313
+ }
314
+
315
+ while ($e = array_pop($exceptions)) {
316
+ $traces = $e->getTrace();
317
+ array_unshift($traces, ['file' => $e->getFile(), 'line' => $e->getLine()]);
318
+
319
+ while ($trace = array_shift($traces)) {
320
+ if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) {
321
+ continue;
322
+ }
323
+
324
+ foreach ($template->getDebugInfo() as $codeLine => $templateLine) {
325
+ if ($codeLine <= $trace['line']) {
326
+ // update template line
327
+ $this->lineno = $templateLine;
328
+
329
+ return;
330
+ }
331
+ }
332
+ }
333
+ }
334
  }
335
  }
336
+
337
+ class_alias('Twig\Error\Error', 'Twig_Error');
src/lib/vendor/twig/twig/src/Error/LoaderError.php CHANGED
@@ -1,11 +1,35 @@
1
  <?php
2
 
3
- namespace Twig\Error;
 
 
 
 
 
 
 
4
 
5
- class_exists('Twig_Error_Loader');
6
 
7
- if (\false) {
8
- class LoaderError extends \Twig_Error_Loader
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
10
  }
11
  }
 
 
1
  <?php
2
 
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
 
12
+ namespace Twig\Error;
13
 
14
+ /**
15
+ * Exception thrown when an error occurs during template loading.
16
+ *
17
+ * Automatic template information guessing is always turned off as
18
+ * if a template cannot be loaded, there is nothing to guess.
19
+ * However, when a template is loaded from another one, then, we need
20
+ * to find the current context and this is automatically done by
21
+ * Twig\Template::displayWithErrorHandling().
22
+ *
23
+ * This strategy makes Twig\Environment::resolveTemplate() much faster.
24
+ *
25
+ * @author Fabien Potencier <fabien@symfony.com>
26
+ */
27
+ class LoaderError extends Error
28
+ {
29
+ public function __construct($message, $lineno = -1, $source = null, \Exception $previous = null)
30
  {
31
+ parent::__construct($message, $lineno, $source, $previous, false);
32
  }
33
  }
34
+
35
+ class_alias('Twig\Error\LoaderError', 'Twig_Error_Loader');
src/lib/vendor/twig/twig/src/Error/RuntimeError.php CHANGED
@@ -1,11 +1,24 @@
1
  <?php
2
 
3
- namespace Twig\Error;
 
 
 
 
 
 
 
 
4
 
5
- class_exists('Twig_Error_Runtime');
6
 
7
- if (\false) {
8
- class RuntimeError extends \Twig_Error_Runtime
9
- {
10
- }
 
 
 
11
  }
 
 
1
  <?php
2
 
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) Fabien Potencier
7
+ * (c) Armin Ronacher
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 Twig\Error;
14
 
15
+ /**
16
+ * Exception thrown when an error occurs at runtime.
17
+ *
18
+ * @author Fabien Potencier <fabien@symfony.com>
19
+ */
20
+ class RuntimeError extends Error
21
+ {
22
  }
23
+
24
+ class_alias('Twig\Error\RuntimeError', 'Twig_Error_Runtime');
src/lib/vendor/twig/twig/src/Error/SyntaxError.php CHANGED
@@ -1,11 +1,57 @@
1
  <?php
2
 
 
 
 
 
 
 
 
 
 
 
3
  namespace Twig\Error;
4
 
5
- class_exists('Twig_Error_Syntax');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- if (\false) {
8
- class SyntaxError extends \Twig_Error_Syntax
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
1
  <?php
2
 
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) Fabien Potencier
7
+ * (c) Armin Ronacher
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 Twig\Error;
14
 
15
+ /**
16
+ * \Exception thrown when a syntax error occurs during lexing or parsing of a template.
17
+ *
18
+ * @author Fabien Potencier <fabien@symfony.com>
19
+ */
20
+ class SyntaxError extends Error
21
+ {
22
+ /**
23
+ * Tweaks the error message to include suggestions.
24
+ *
25
+ * @param string $name The original name of the item that does not exist
26
+ * @param array $items An array of possible items
27
+ */
28
+ public function addSuggestions($name, array $items)
29
+ {
30
+ if (!$alternatives = self::computeAlternatives($name, $items)) {
31
+ return;
32
+ }
33
+
34
+ $this->appendMessage(sprintf(' Did you mean "%s"?', implode('", "', $alternatives)));
35
+ }
36
 
37
+ /**
38
+ * @internal
39
+ *
40
+ * To be merged with the addSuggestions() method in 2.0.
41
+ */
42
+ public static function computeAlternatives($name, $items)
43
  {
44
+ $alternatives = [];
45
+ foreach ($items as $item) {
46
+ $lev = levenshtein($name, $item);
47
+ if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) {
48
+ $alternatives[$item] = $lev;
49
+ }
50
+ }
51
+ asort($alternatives);
52
+
53
+ return array_keys($alternatives);
54
  }
55
  }
56
+
57
+ class_alias('Twig\Error\SyntaxError', 'Twig_Error_Syntax');
src/lib/vendor/twig/twig/src/ExpressionParser.php CHANGED
@@ -1,11 +1,765 @@
1
  <?php
2
 
 
 
 
 
 
 
 
 
 
 
3
  namespace Twig;
4
 
5
- class_exists('Twig_ExpressionParser');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- if (\false) {
8
- class ExpressionParser extends \Twig_ExpressionParser
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
1
  <?php
2
 
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) Fabien Potencier
7
+ * (c) Armin Ronacher
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 Twig;
14
 
15
+ use Twig\Error\SyntaxError;
16
+ use Twig\Node\Expression\ArrayExpression;
17
+ use Twig\Node\Expression\AssignNameExpression;
18
+ use Twig\Node\Expression\Binary\ConcatBinary;
19
+ use Twig\Node\Expression\BlockReferenceExpression;
20
+ use Twig\Node\Expression\ConditionalExpression;
21
+ use Twig\Node\Expression\ConstantExpression;
22
+ use Twig\Node\Expression\GetAttrExpression;
23
+ use Twig\Node\Expression\MethodCallExpression;
24
+ use Twig\Node\Expression\NameExpression;
25
+ use Twig\Node\Expression\ParentExpression;
26
+ use Twig\Node\Expression\Unary\NegUnary;
27
+ use Twig\Node\Expression\Unary\NotUnary;
28
+ use Twig\Node\Expression\Unary\PosUnary;
29
+ use Twig\Node\Node;
30
+
31
+ /**
32
+ * Parses expressions.
33
+ *
34
+ * This parser implements a "Precedence climbing" algorithm.
35
+ *
36
+ * @see https://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
37
+ * @see https://en.wikipedia.org/wiki/Operator-precedence_parser
38
+ *
39
+ * @author Fabien Potencier <fabien@symfony.com>
40
+ *
41
+ * @internal
42
+ */
43
+ class ExpressionParser
44
+ {
45
+ const OPERATOR_LEFT = 1;
46
+ const OPERATOR_RIGHT = 2;
47
+
48
+ protected $parser;
49
+ protected $unaryOperators;
50
+ protected $binaryOperators;
51
+
52
+ private $env;
53
+
54
+ public function __construct(Parser $parser, $env = null)
55
+ {
56
+ $this->parser = $parser;
57
+
58
+ if ($env instanceof Environment) {
59
+ $this->env = $env;
60
+ $this->unaryOperators = $env->getUnaryOperators();
61
+ $this->binaryOperators = $env->getBinaryOperators();
62
+ } else {
63
+ @trigger_error('Passing the operators as constructor arguments to '.__METHOD__.' is deprecated since version 1.27. Pass the environment instead.', E_USER_DEPRECATED);
64
+
65
+ $this->env = $parser->getEnvironment();
66
+ $this->unaryOperators = func_get_arg(1);
67
+ $this->binaryOperators = func_get_arg(2);
68
+ }
69
+ }
70
+
71
+ public function parseExpression($precedence = 0)
72
+ {
73
+ $expr = $this->getPrimary();
74
+ $token = $this->parser->getCurrentToken();
75
+ while ($this->isBinary($token) && $this->binaryOperators[$token->getValue()]['precedence'] >= $precedence) {
76
+ $op = $this->binaryOperators[$token->getValue()];
77
+ $this->parser->getStream()->next();
78
+
79
+ if ('is not' === $token->getValue()) {
80
+ $expr = $this->parseNotTestExpression($expr);
81
+ } elseif ('is' === $token->getValue()) {
82
+ $expr = $this->parseTestExpression($expr);
83
+ } elseif (isset($op['callable'])) {
84
+ $expr = \call_user_func($op['callable'], $this->parser, $expr);
85
+ } else {
86
+ $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']);
87
+ $class = $op['class'];
88
+ $expr = new $class($expr, $expr1, $token->getLine());
89
+ }
90
+
91
+ $token = $this->parser->getCurrentToken();
92
+ }
93
+
94
+ if (0 === $precedence) {
95
+ return $this->parseConditionalExpression($expr);
96
+ }
97
+
98
+ return $expr;
99
+ }
100
+
101
+ protected function getPrimary()
102
+ {
103
+ $token = $this->parser->getCurrentToken();
104
+
105
+ if ($this->isUnary($token)) {
106
+ $operator = $this->unaryOperators[$token->getValue()];
107
+ $this->parser->getStream()->next();
108
+ $expr = $this->parseExpression($operator['precedence']);
109
+ $class = $operator['class'];
110
+
111
+ return $this->parsePostfixExpression(new $class($expr, $token->getLine()));
112
+ } elseif ($token->test(Token::PUNCTUATION_TYPE, '(')) {
113
+ $this->parser->getStream()->next();
114
+ $expr = $this->parseExpression();
115
+ $this->parser->getStream()->expect(Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed');
116
+
117
+ return $this->parsePostfixExpression($expr);
118
+ }
119
+
120
+ return $this->parsePrimaryExpression();
121
+ }
122
 
123
+ protected function parseConditionalExpression($expr)
 
124
  {
125
+ while ($this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, '?')) {
126
+ if (!$this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, ':')) {
127
+ $expr2 = $this->parseExpression();
128
+ if ($this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, ':')) {
129
+ $expr3 = $this->parseExpression();
130
+ } else {
131
+ $expr3 = new ConstantExpression('', $this->parser->getCurrentToken()->getLine());
132
+ }
133
+ } else {
134
+ $expr2 = $expr;
135
+ $expr3 = $this->parseExpression();
136
+ }
137
+
138
+ $expr = new ConditionalExpression($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine());
139
+ }
140
+
141
+ return $expr;
142
+ }
143
+
144
+ protected function isUnary(Token $token)
145
+ {
146
+ return $token->test(Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]);
147
+ }
148
+
149
+ protected function isBinary(Token $token)
150
+ {
151
+ return $token->test(Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]);
152
+ }
153
+
154
+ public function parsePrimaryExpression()
155
+ {
156
+ $token = $this->parser->getCurrentToken();
157
+ switch ($token->getType()) {
158
+ case Token::NAME_TYPE:
159
+ $this->parser->getStream()->next();
160
+ switch ($token->getValue()) {
161
+ case 'true':
162
+ case 'TRUE':
163
+ $node = new ConstantExpression(true, $token->getLine());
164
+ break;
165
+
166
+ case 'false':
167
+ case 'FALSE':
168
+ $node = new ConstantExpression(false, $token->getLine());
169
+ break;
170
+
171
+ case 'none':
172
+ case 'NONE':
173
+ case 'null':
174
+ case 'NULL':
175
+ $node = new ConstantExpression(null, $token->getLine());
176
+ break;
177
+
178
+ default:
179
+ if ('(' === $this->parser->getCurrentToken()->getValue()) {
180
+ $node = $this->getFunctionNode($token->getValue(), $token->getLine());
181
+ } else {
182
+ $node = new NameExpression($token->getValue(), $token->getLine());
183
+ }
184
+ }
185
+ break;
186
+
187
+ case Token::NUMBER_TYPE:
188
+ $this->parser->getStream()->next();
189
+ $node = new ConstantExpression($token->getValue(), $token->getLine());
190
+ break;
191
+
192
+ case Token::STRING_TYPE:
193
+ case Token::INTERPOLATION_START_TYPE:
194
+ $node = $this->parseStringExpression();
195
+ break;
196
+
197
+ case Token::OPERATOR_TYPE:
198
+ if (preg_match(Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) {
199
+ // in this context, string operators are variable names
200
+ $this->parser->getStream()->next();
201
+ $node = new NameExpression($token->getValue(), $token->getLine());
202
+ break;
203
+ } elseif (isset($this->unaryOperators[$token->getValue()])) {
204
+ $class = $this->unaryOperators[$token->getValue()]['class'];
205
+
206
+ $ref = new \ReflectionClass($class);
207
+ $negClass = 'Twig\Node\Expression\Unary\NegUnary';
208
+ $posClass = 'Twig\Node\Expression\Unary\PosUnary';
209
+ if (!(\in_array($ref->getName(), [$negClass, $posClass, 'Twig_Node_Expression_Unary_Neg', 'Twig_Node_Expression_Unary_Pos'])
210
+ || $ref->isSubclassOf($negClass) || $ref->isSubclassOf($posClass)
211
+ || $ref->isSubclassOf('Twig_Node_Expression_Unary_Neg') || $ref->isSubclassOf('Twig_Node_Expression_Unary_Pos'))
212
+ ) {
213
+ throw new SyntaxError(sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext());
214
+ }
215
+
216
+ $this->parser->getStream()->next();
217
+ $expr = $this->parsePrimaryExpression();
218
+
219
+ $node = new $class($expr, $token->getLine());
220
+ break;
221
+ }
222
+
223
+ // no break
224
+ default:
225
+ if ($token->test(Token::PUNCTUATION_TYPE, '[')) {
226
+ $node = $this->parseArrayExpression();
227
+ } elseif ($token->test(Token::PUNCTUATION_TYPE, '{')) {
228
+ $node = $this->parseHashExpression();
229
+ } elseif ($token->test(Token::OPERATOR_TYPE, '=') && ('==' === $this->parser->getStream()->look(-1)->getValue() || '!=' === $this->parser->getStream()->look(-1)->getValue())) {
230
+ throw new SyntaxError(sprintf('Unexpected operator of value "%s". Did you try to use "===" or "!==" for strict comparison? Use "is same as(value)" instead.', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext());
231
+ } else {
232
+ throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s".', Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext());
233
+ }
234
+ }
235
+
236
+ return $this->parsePostfixExpression($node);
237
+ }
238
+
239
+ public function parseStringExpression()
240
+ {
241
+ $stream = $this->parser->getStream();
242
+
243
+ $nodes = [];
244
+ // a string cannot be followed by another string in a single expression
245
+ $nextCanBeString = true;
246
+ while (true) {
247
+ if ($nextCanBeString && $token = $stream->nextIf(Token::STRING_TYPE)) {
248
+ $nodes[] = new ConstantExpression($token->getValue(), $token->getLine());
249
+ $nextCanBeString = false;
250
+ } elseif ($stream->nextIf(Token::INTERPOLATION_START_TYPE)) {
251
+ $nodes[] = $this->parseExpression();
252
+ $stream->expect(Token::INTERPOLATION_END_TYPE);
253
+ $nextCanBeString = true;
254
+ } else {
255
+ break;
256
+ }
257
+ }
258
+
259
+ $expr = array_shift($nodes);
260
+ foreach ($nodes as $node) {
261
+ $expr = new ConcatBinary($expr, $node, $node->getTemplateLine());
262
+ }
263
+
264
+ return $expr;
265
+ }
266
+
267
+ public function parseArrayExpression()
268
+ {
269
+ $stream = $this->parser->getStream();
270
+ $stream->expect(Token::PUNCTUATION_TYPE, '[', 'An array element was expected');
271
+
272
+ $node = new ArrayExpression([], $stream->getCurrent()->getLine());
273
+ $first = true;
274
+ while (!$stream->test(Token::PUNCTUATION_TYPE, ']')) {
275
+ if (!$first) {
276
+ $stream->expect(Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma');
277
+
278
+ // trailing ,?
279
+ if ($stream->test(Token::PUNCTUATION_TYPE, ']')) {
280
+ break;
281
+ }
282
+ }
283
+ $first = false;
284
+
285
+ $node->addElement($this->parseExpression());
286
+ }
287
+ $stream->expect(Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed');
288
+
289
+ return $node;
290
+ }
291
+
292
+ public function parseHashExpression()
293
+ {
294
+ $stream = $this->parser->getStream();
295
+ $stream->expect(Token::PUNCTUATION_TYPE, '{', 'A hash element was expected');
296
+
297
+ $node = new ArrayExpression([], $stream->getCurrent()->getLine());
298
+ $first = true;
299
+ while (!$stream->test(Token::PUNCTUATION_TYPE, '}')) {
300
+ if (!$first) {
301
+ $stream->expect(Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma');
302
+
303
+ // trailing ,?
304
+ if ($stream->test(Token::PUNCTUATION_TYPE, '}')) {
305
+ break;
306
+ }
307
+ }
308
+ $first = false;
309
+
310
+ // a hash key can be:
311
+ //
312
+ // * a number -- 12
313
+ // * a string -- 'a'
314
+ // * a name, which is equivalent to a string -- a
315
+ // * an expression, which must be enclosed in parentheses -- (1 + 2)
316
+ if (($token = $stream->nextIf(Token::STRING_TYPE)) || ($token = $stream->nextIf(Token::NAME_TYPE)) || $token = $stream->nextIf(Token::NUMBER_TYPE)) {
317
+ $key = new ConstantExpression($token->getValue(), $token->getLine());
318
+ } elseif ($stream->test(Token::PUNCTUATION_TYPE, '(')) {
319
+ $key = $this->parseExpression();
320
+ } else {
321
+ $current = $stream->getCurrent();
322
+
323
+ throw new SyntaxError(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s".', Token::typeToEnglish($current->getType()), $current->getValue()), $current->getLine(), $stream->getSourceContext());
324
+ }
325
+
326
+ $stream->expect(Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)');
327
+ $value = $this->parseExpression();
328
+
329
+ $node->addElement($value, $key);
330
+ }
331
+ $stream->expect(Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed');
332
+
333
+ return $node;
334
+ }
335
+
336
+ public function parsePostfixExpression($node)
337
+ {
338
+ while (true) {
339
+ $token = $this->parser->getCurrentToken();
340
+ if (Token::PUNCTUATION_TYPE == $token->getType()) {
341
+ if ('.' == $token->getValue() || '[' == $token->getValue()) {
342
+ $node = $this->parseSubscriptExpression($node);
343
+ } elseif ('|' == $token->getValue()) {
344
+ $node = $this->parseFilterExpression($node);
345
+ } else {
346
+ break;
347
+ }
348
+ } else {
349
+ break;
350
+ }
351
+ }
352
+
353
+ return $node;
354
+ }
355
+
356
+ public function getFunctionNode($name, $line)
357
+ {
358
+ switch ($name) {
359
+ case 'parent':
360
+ $this->parseArguments();
361
+ if (!\count($this->parser->getBlockStack())) {
362
+ throw new SyntaxError('Calling "parent" outside a block is forbidden.', $line, $this->parser->getStream()->getSourceContext());
363
+ }
364
+
365
+ if (!$this->parser->getParent() && !$this->parser->hasTraits()) {
366
+ throw new SyntaxError('Calling "parent" on a template that does not extend nor "use" another template is forbidden.', $line, $this->parser->getStream()->getSourceContext());
367
+ }
368
+
369
+ return new ParentExpression($this->parser->peekBlockStack(), $line);
370
+ case 'block':
371
+ $args = $this->parseArguments();
372
+ if (\count($args) < 1) {
373
+ throw new SyntaxError('The "block" function takes one argument (the block name).', $line, $this->parser->getStream()->getSourceContext());
374
+ }
375
+
376
+ return new BlockReferenceExpression($args->getNode(0), \count($args) > 1 ? $args->getNode(1) : null, $line);
377
+ case 'attribute':
378
+ $args = $this->parseArguments();
379
+ if (\count($args) < 2) {
380
+ throw new SyntaxError('The "attribute" function takes at least two arguments (the variable and the attributes).', $line, $this->parser->getStream()->getSourceContext());
381
+ }
382
+
383
+ return new GetAttrExpression($args->getNode(0), $args->getNode(1), \count($args) > 2 ? $args->getNode(2) : null, Template::ANY_CALL, $line);
384
+ default:
385
+ if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) {
386
+ $arguments = new ArrayExpression([], $line);
387
+ foreach ($this->parseArguments() as $n) {
388
+ $arguments->addElement($n);
389
+ }
390
+
391
+ $node = new MethodCallExpression($alias['node'], $alias['name'], $arguments, $line);
392
+ $node->setAttribute('safe', true);
393
+
394
+ return $node;
395
+ }
396
+
397
+ $args = $this->parseArguments(true);
398
+ $class = $this->getFunctionNodeClass($name, $line);
399
+
400
+ return new $class($name, $args, $line);
401
+ }
402
+ }
403
+
404
+ public function parseSubscriptExpression($node)
405
+ {
406
+ $stream = $this->parser->getStream();
407
+ $token = $stream->next();
408
+ $lineno = $token->getLine();
409
+ $arguments = new ArrayExpression([], $lineno);
410
+ $type = Template::ANY_CALL;
411
+ if ('.' == $token->getValue()) {
412
+ $token = $stream->next();
413
+ if (
414
+ Token::NAME_TYPE == $token->getType()
415
+ ||
416
+ Token::NUMBER_TYPE == $token->getType()
417
+ ||
418
+ (Token::OPERATOR_TYPE == $token->getType() && preg_match(Lexer::REGEX_NAME, $token->getValue()))
419
+ ) {
420
+ $arg = new ConstantExpression($token->getValue(), $lineno);
421
+
422
+ if ($stream->test(Token::PUNCTUATION_TYPE, '(')) {
423
+ $type = Template::METHOD_CALL;
424
+ foreach ($this->parseArguments() as $n) {
425
+ $arguments->addElement($n);
426
+ }
427
+ }
428
+ } else {
429
+ throw new SyntaxError('Expected name or number.', $lineno, $stream->getSourceContext());
430
+ }
431
+
432
+ if ($node instanceof NameExpression && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
433
+ if (!$arg instanceof ConstantExpression) {
434
+ throw new SyntaxError(sprintf('Dynamic macro names are not supported (called on "%s").', $node->getAttribute('name')), $token->getLine(), $stream->getSourceContext());
435
+ }
436
+
437
+ $name = $arg->getAttribute('value');
438
+
439
+ if ($this->parser->isReservedMacroName($name)) {
440
+ throw new SyntaxError(sprintf('"%s" cannot be called as macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext());
441
+ }
442
+
443
+ $node = new MethodCallExpression($node, 'get'.$name, $arguments, $lineno);
444
+ $node->setAttribute('safe', true);
445
+
446
+ return $node;
447
+ }
448
+ } else {
449
+ $type = Template::ARRAY_CALL;
450
+
451
+ // slice?
452
+ $slice = false;
453
+ if ($stream->test(Token::PUNCTUATION_TYPE, ':')) {
454
+ $slice = true;
455
+ $arg = new ConstantExpression(0, $token->getLine());
456
+ } else {
457
+ $arg = $this->parseExpression();
458
+ }
459
+
460
+ if ($stream->nextIf(Token::PUNCTUATION_TYPE, ':')) {
461
+ $slice = true;
462
+ }
463
+
464
+ if ($slice) {
465
+ if ($stream->test(Token::PUNCTUATION_TYPE, ']')) {
466
+ $length = new ConstantExpression(null, $token->getLine());
467
+ } else {
468
+ $length = $this->parseExpression();
469
+ }
470
+
471
+ $class = $this->getFilterNodeClass('slice', $token->getLine());
472
+ $arguments = new Node([$arg, $length]);
473
+ $filter = new $class($node, new ConstantExpression('slice', $token->getLine()), $arguments, $token->getLine());
474
+
475
+ $stream->expect(Token::PUNCTUATION_TYPE, ']');
476
+
477
+ return $filter;
478
+ }
479
+
480
+ $stream->expect(Token::PUNCTUATION_TYPE, ']');
481
+ }
482
+
483
+ return new GetAttrExpression($node, $arg, $arguments, $type, $lineno);
484
+ }
485
+
486
+ public function parseFilterExpression($node)
487
+ {
488
+ $this->parser->getStream()->next();
489
+
490
+ return $this->parseFilterExpressionRaw($node);
491
+ }
492
+
493
+ public function parseFilterExpressionRaw($node, $tag = null)
494
+ {
495
+ while (true) {
496
+ $token = $this->parser->getStream()->expect(Token::NAME_TYPE);
497
+
498
+ $name = new ConstantExpression($token->getValue(), $token->getLine());
499
+ if (!$this->parser->getStream()->test(Token::PUNCTUATION_TYPE, '(')) {
500
+ $arguments = new Node();
501
+ } else {
502
+ $arguments = $this->parseArguments(true);
503
+ }
504
+
505
+ $class = $this->getFilterNodeClass($name->getAttribute('value'), $token->getLine());
506
+
507
+ $node = new $class($node, $name, $arguments, $token->getLine(), $tag);
508
+
509
+ if (!$this->parser->getStream()->test(Token::PUNCTUATION_TYPE, '|')) {
510
+ break;
511
+ }
512
+
513
+ $this->parser->getStream()->next();
514
+ }
515
+
516
+ return $node;
517
+ }
518
+
519
+ /**
520
+ * Parses arguments.
521
+ *
522
+ * @param bool $namedArguments Whether to allow named arguments or not
523
+ * @param bool $definition Whether we are parsing arguments for a function definition
524
+ *
525
+ * @return Node
526
+ *
527
+ * @throws SyntaxError
528
+ */
529
+ public function parseArguments($namedArguments = false, $definition = false)
530
+ {
531
+ $args = [];
532
+ $stream = $this->parser->getStream();
533
+
534
+ $stream->expect(Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis');
535
+ while (!$stream->test(Token::PUNCTUATION_TYPE, ')')) {
536
+ if (!empty($args)) {
537
+ $stream->expect(Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma');
538
+ }
539
+
540
+ if ($definition) {
541
+ $token = $stream->expect(Token::NAME_TYPE, null, 'An argument must be a name');
542
+ $value = new NameExpression($token->getValue(), $this->parser->getCurrentToken()->getLine());
543
+ } else {
544
+ $value = $this->parseExpression();
545
+ }
546
+
547
+ $name = null;
548
+ if ($namedArguments && $token = $stream->nextIf(Token::OPERATOR_TYPE, '=')) {
549
+ if (!$value instanceof NameExpression) {
550
+ throw new SyntaxError(sprintf('A parameter name must be a string, "%s" given.', \get_class($value)), $token->getLine(), $stream->getSourceContext());
551
+ }
552
+ $name = $value->getAttribute('name');
553
+
554
+ if ($definition) {
555
+ $value = $this->parsePrimaryExpression();
556
+
557
+ if (!$this->checkConstantExpression($value)) {
558
+ throw new SyntaxError(sprintf('A default value for an argument must be a constant (a boolean, a string, a number, or an array).'), $token->getLine(), $stream->getSourceContext());
559
+ }
560
+ } else {
561
+ $value = $this->parseExpression();
562
+ }
563
+ }
564
+
565
+ if ($definition) {
566
+ if (null === $name) {
567
+ $name = $value->getAttribute('name');
568
+ $value = new ConstantExpression(null, $this->parser->getCurrentToken()->getLine());
569
+ }
570
+ $args[$name] = $value;
571
+ } else {
572
+ if (null === $name) {
573
+ $args[] = $value;
574
+ } else {
575
+ $args[$name] = $value;
576
+ }
577
+ }
578
+ }
579
+ $stream->expect(Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis');
580
+
581
+ return new Node($args);
582
+ }
583
+
584
+ public function parseAssignmentExpression()
585
+ {
586
+ $stream = $this->parser->getStream();
587
+ $targets = [];
588
+ while (true) {
589
+ $token = $stream->expect(Token::NAME_TYPE, null, 'Only variables can be assigned to');
590
+ $value = $token->getValue();
591
+ if (\in_array(strtolower($value), ['true', 'false', 'none', 'null'])) {
592
+ throw new SyntaxError(sprintf('You cannot assign a value to "%s".', $value), $token->getLine(), $stream->getSourceContext());
593
+ }
594
+ $targets[] = new AssignNameExpression($value, $token->getLine());
595
+
596
+ if (!$stream->nextIf(Token::PUNCTUATION_TYPE, ',')) {
597
+ break;
598
+ }
599
+ }
600
+
601
+ return new Node($targets);
602
+ }
603
+
604
+ public function parseMultitargetExpression()
605
+ {
606
+ $targets = [];
607
+ while (true) {
608
+ $targets[] = $this->parseExpression();
609
+ if (!$this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, ',')) {
610
+ break;
611
+ }
612
+ }
613
+
614
+ return new Node($targets);
615
+ }
616
+
617
+ private function parseNotTestExpression(\Twig_NodeInterface $node)
618
+ {
619
+ return new NotUnary($this->parseTestExpression($node), $this->parser->getCurrentToken()->getLine());
620
+ }
621
+
622
+ private function parseTestExpression(\Twig_NodeInterface $node)
623
+ {
624
+ $stream = $this->parser->getStream();
625
+ list($name, $test) = $this->getTest($node->getTemplateLine());
626
+
627
+ $class = $this->getTestNodeClass($test);
628
+ $arguments = null;
629
+ if ($stream->test(Token::PUNCTUATION_TYPE, '(')) {
630
+ $arguments = $this->parser->getExpressionParser()->parseArguments(true);
631
+ }
632
+
633
+ return new $class($node, $name, $arguments, $this->parser->getCurrentToken()->getLine());
634
+ }
635
+
636
+ private function getTest($line)
637
+ {
638
+ $stream = $this->parser->getStream();
639
+ $name = $stream->expect(Token::NAME_TYPE)->getValue();
640
+
641
+ if ($test = $this->env->getTest($name)) {
642
+ return [$name, $test];
643
+ }
644
+
645
+ if ($stream->test(Token::NAME_TYPE)) {
646
+ // try 2-words tests
647
+ $name = $name.' '.$this->parser->getCurrentToken()->getValue();
648
+
649
+ if ($test = $this->env->getTest($name)) {
650
+ $stream->next();
651
+
652
+ return [$name, $test];
653
+ }
654
+ }
655
+
656
+ $e = new SyntaxError(sprintf('Unknown "%s" test.', $name), $line, $stream->getSourceContext());
657
+ $e->addSuggestions($name, array_keys($this->env->getTests()));
658
+
659
+ throw $e;
660
+ }
661
+
662
+ private function getTestNodeClass($test)
663
+ {
664
+ if ($test instanceof TwigTest && $test->isDeprecated()) {
665
+ $stream = $this->parser->getStream();
666
+ $message = sprintf('Twig Test "%s" is deprecated', $test->getName());
667
+ if (!\is_bool($test->getDeprecatedVersion())) {
668
+ $message .= sprintf(' since version %s', $test->getDeprecatedVersion());
669
+ }
670
+ if ($test->getAlternative()) {
671
+ $message .= sprintf('. Use "%s" instead', $test->getAlternative());
672
+ }
673
+ $src = $stream->getSourceContext();
674
+ $message .= sprintf(' in %s at line %d.', $src->getPath() ? $src->getPath() : $src->getName(), $stream->getCurrent()->getLine());
675
+
676
+ @trigger_error($message, E_USER_DEPRECATED);
677
+ }
678
+
679
+ if ($test instanceof TwigTest) {
680
+ return $test->getNodeClass();
681
+ }
682
+
683
+ return $test instanceof \Twig_Test_Node ? $test->getClass() : 'Twig\Node\Expression\TestExpression';
684
+ }
685
+
686
+ protected function getFunctionNodeClass($name, $line)
687
+ {
688
+ if (false === $function = $this->env->getFunction($name)) {
689
+ $e = new SyntaxError(sprintf('Unknown "%s" function.', $name), $line, $this->parser->getStream()->getSourceContext());
690
+ $e->addSuggestions($name, array_keys($this->env->getFunctions()));
691
+
692
+ throw $e;
693
+ }
694
+
695
+ if ($function instanceof TwigFunction && $function->isDeprecated()) {
696
+ $message = sprintf('Twig Function "%s" is deprecated', $function->getName());
697
+ if (!\is_bool($function->getDeprecatedVersion())) {
698
+ $message .= sprintf(' since version %s', $function->getDeprecatedVersion());
699
+ }
700
+ if ($function->getAlternative()) {
701
+ $message .= sprintf('. Use "%s" instead', $function->getAlternative());
702
+ }
703
+ $src = $this->parser->getStream()->getSourceContext();
704
+ $message .= sprintf(' in %s at line %d.', $src->getPath() ? $src->getPath() : $src->getName(), $line);
705
+
706
+ @trigger_error($message, E_USER_DEPRECATED);
707
+ }
708
+
709
+ if ($function instanceof TwigFunction) {
710
+ return $function->getNodeClass();
711
+ }
712
+
713
+ return $function instanceof \Twig_Function_Node ? $function->getClass() : 'Twig\Node\Expression\FunctionExpression';
714
+ }
715
+
716
+ protected function getFilterNodeClass($name, $line)
717
+ {
718
+ if (false === $filter = $this->env->getFilter($name)) {
719
+ $e = new SyntaxError(sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getStream()->getSourceContext());
720
+ $e->addSuggestions($name, array_keys($this->env->getFilters()));
721
+
722
+ throw $e;
723
+ }
724
+
725
+ if ($filter instanceof TwigFilter && $filter->isDeprecated()) {
726
+ $message = sprintf('Twig Filter "%s" is deprecated', $filter->getName());
727
+ if (!\is_bool($filter->getDeprecatedVersion())) {
728
+ $message .= sprintf(' since version %s', $filter->getDeprecatedVersion());
729
+ }
730
+ if ($filter->getAlternative()) {
731
+ $message .= sprintf('. Use "%s" instead', $filter->getAlternative());
732
+ }
733
+ $src = $this->parser->getStream()->getSourceContext();
734
+ $message .= sprintf(' in %s at line %d.', $src->getPath() ? $src->getPath() : $src->getName(), $line);
735
+
736
+ @trigger_error($message, E_USER_DEPRECATED);
737
+ }
738
+
739
+ if ($filter instanceof TwigFilter) {
740
+ return $filter->getNodeClass();
741
+ }
742
+
743
+ return $filter instanceof \Twig_Filter_Node ? $filter->getClass() : 'Twig\Node\Expression\FilterExpression';
744
+ }
745
+
746
+ // checks that the node only contains "constant" elements
747
+ protected function checkConstantExpression(\Twig_NodeInterface $node)
748
+ {
749
+ if (!($node instanceof ConstantExpression || $node instanceof ArrayExpression
750
+ || $node instanceof NegUnary || $node instanceof PosUnary
751
+ )) {
752
+ return false;
753
+ }
754
+
755
+ foreach ($node as $n) {
756
+ if (!$this->checkConstantExpression($n)) {
757
+ return false;
758
+ }
759
+ }
760
+
761
+ return true;
762
  }
763
  }
764
+
765
+ class_alias('Twig\ExpressionParser', 'Twig_ExpressionParser');
src/lib/vendor/twig/twig/src/Extension/AbstractExtension.php CHANGED
@@ -1,11 +1,72 @@
1
  <?php
2
 
 
 
 
 
 
 
 
 
 
3
  namespace Twig\Extension;
4
 
5
- class_exists('Twig_Extension');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- if (\false) {
8
- class AbstractExtension extends \Twig_Extension
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
  }
 
 
1
  <?php
2
 
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
  namespace Twig\Extension;
13
 
14
+ use Twig\Environment;
15
+
16
+ abstract class AbstractExtension implements ExtensionInterface
17
+ {
18
+ /**
19
+ * @deprecated since 1.23 (to be removed in 2.0), implement \Twig_Extension_InitRuntimeInterface instead
20
+ */
21
+ public function initRuntime(Environment $environment)
22
+ {
23
+ }
24
+
25
+ public function getTokenParsers()
26
+ {
27
+ return [];
28
+ }
29
+
30
+ public function getNodeVisitors()
31
+ {
32
+ return [];
33
+ }
34
+
35
+ public function getFilters()
36
+ {
37
+ return [];
38
+ }
39
+
40
+ public function getTests()
41
+ {
42
+ return [];
43
+ }
44
 
45
+ public function getFunctions()
 
46
  {
47
+ return [];
48
+ }
49
+
50
+ public function getOperators()
51
+ {
52
+ return [];
53
+ }
54
+
55
+ /**
56
+ * @deprecated since 1.23 (to be removed in 2.0), implement \Twig_Extension_GlobalsInterface instead
57
+ */
58
+ public function getGlobals()
59
+ {
60
+ return [];
61
+ }
62
+
63
+ /**
64
+ * @deprecated since 1.26 (to be removed in 2.0), not used anymore internally
65
+ */
66
+ public function getName()
67
+ {
68
+ return \get_class($this);
69
  }
70
  }
71
+
72
+ class_alias('Twig\Extension\AbstractExtension', 'Twig_Extension');
src/lib/vendor/twig/twig/src/Extension/CoreExtension.php CHANGED
@@ -1,11 +1,1667 @@
1
  <?php
2
 
3
- namespace Twig\Extension;
 
 
 
 
 
 
 
4
 
5
- class_exists('Twig_Extension_Core');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
- if (\false) {
8
- class CoreExtension extends \Twig_Extension_Core
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
 
3
+ /*
4
+ * This file is part of Twig.
5
+ *
6
+ * (c) Fabien Potencier
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
 
12
+ namespace Twig\Extension {
13
+ use Twig\ExpressionParser;
14
+ use Twig\TokenParser\BlockTokenParser;
15
+ use Twig\TokenParser\DeprecatedTokenParser;
16
+ use Twig\TokenParser\DoTokenParser;
17
+ use Twig\TokenParser\EmbedTokenParser;
18
+ use Twig\TokenParser\ExtendsTokenParser;
19
+ use Twig\TokenParser\FilterTokenParser;
20
+ use Twig\TokenParser\FlushTokenParser;
21
+ use Twig\TokenParser\ForTokenParser;
22
+ use Twig\TokenParser\FromTokenParser;
23
+ use Twig\TokenParser\IfTokenParser;
24
+ use Twig\TokenParser\ImportTokenParser;
25
+ use Twig\TokenParser\IncludeTokenParser;
26
+ use Twig\TokenParser\MacroTokenParser;
27
+ use Twig\TokenParser\SetTokenParser;
28
+ use Twig\TokenParser\SpacelessTokenParser;
29
+ use Twig\TokenParser\UseTokenParser;
30
+ use Twig\TokenParser\WithTokenParser;
31
+ use Twig\TwigFilter;
32
+ use Twig\TwigFunction;
33
+ use Twig\TwigTest;
34
 
35
+ /**
36
+ * @final
37
+ */
38
+ class CoreExtension extends AbstractExtension
39
+ {
40
+ protected $dateFormats = ['F j, Y H:i', '%d days'];
41
+ protected $numberFormat = [0, '.', ','];
42
+ protected $timezone = null;
43
+ protected $escapers = [];
44
+
45
+ /**
46
+ * Defines a new escaper to be used via the escape filter.
47
+ *
48
+ * @param string $strategy The strategy name that should be used as a strategy in the escape call
49
+ * @param callable $callable A valid PHP callable
50
+ */
51
+ public function setEscaper($strategy, $callable)
52
+ {
53
+ $this->escapers[$strategy] = $callable;
54
+ }
55
+
56
+ /**
57
+ * Gets all defined escapers.
58
+ *
59
+ * @return array An array of escapers
60
+ */
61
+ public function getEscapers()
62
+ {
63
+ return $this->escapers;
64
+ }
65
+
66
+ /**
67
+ * Sets the default format to be used by the date filter.
68
+ *
69
+ * @param string $format The default date format string
70
+ * @param string $dateIntervalFormat The default date interval format string
71
+ */
72
+ public function setDateFormat($format = null, $dateIntervalFormat = null)
73
  {
74
+ if (null !== $format) {
75
+ $this->dateFormats[0] = $format;
76
+ }
77
+
78
+ if (null !== $dateIntervalFormat) {
79
+ $this->dateFormats[1] = $dateIntervalFormat;
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Gets the default format to be used by the date filter.
85
+ *
86
+ * @return array The default date format string and the default date interval format string
87
+ */
88
+ public function getDateFormat()
89
+ {
90
+ return $this->dateFormats;
91
+ }
92
+
93
+ /**
94
+ * Sets the default timezone to be used by the date filter.
95
+ *
96
+ * @param \DateTimeZone|string $timezone The default timezone string or a \DateTimeZone object
97
+ */
98
+ public function setTimezone($timezone)
99
+ {
100
+ $this->timezone = $timezone instanceof \DateTimeZone ? $timezone : new \DateTimeZone($timezone);
101
+ }
102
+
103
+ /**
104
+ * Gets the default timezone to be used by the date filter.
105
+ *
106
+ * @return \DateTimeZone The default timezone currently in use
107
+ */
108
+ public function getTimezone()
109
+ {
110
+ if (null === $this->timezone) {
111
+ $this->timezone = new \DateTimeZone(date_default_timezone_get());
112
+ }
113
+
114
+ return $this->timezone;
115
+ }
116
+
117
+ /**
118
+ * Sets the default format to be used by the number_format filter.
119
+ *
120
+ * @param int $decimal the number of decimal places to use
121
+ * @param string $decimalPoint the character(s) to use for the decimal point
122
+ * @param string $thousandSep the character(s) to use for the thousands separator
123
+ */
124
+ public function setNumberFormat($decimal, $decimalPoint, $thousandSep)
125
+ {
126
+ $this->numberFormat = [$decimal, $decimalPoint, $thousandSep];
127
+ }
128
+
129
+ /**
130
+ * Get the default format used by the number_format filter.
131
+ *
132
+ * @return array The arguments for number_format()
133
+ */
134
+ public function getNumberFormat()
135
+ {
136
+ return $this->numberFormat;
137
+ }
138
+
139
+ public function getTokenParsers()
140
+ {
141
+ return [
142
+ new ForTokenParser(),
143
+ new IfTokenParser(),
144
+ new ExtendsTokenParser(),
145
+ new IncludeTokenParser(),
146
+ new BlockTokenParser(),
147
+ new UseTokenParser(),
148
+ new FilterTokenParser(),
149
+ new MacroTokenParser(),
150
+ new ImportTokenParser(),
151
+ new FromTokenParser(),
152
+ new SetTokenParser(),
153
+ new SpacelessTokenParser(),
154
+ new FlushTokenParser(),
155
+ new DoTokenParser(),
156
+ new EmbedTokenParser(),
157
+ new WithTokenParser(),
158
+ new DeprecatedTokenParser(),
159
+ ];
160
+ }
161
+
162
+ public function getFilters()
163
+ {
164
+ $filters = [
165
+ // formatting filters
166
+ new TwigFilter('date', 'twig_date_format_filter', ['needs_environment' => true]),
167
+ new TwigFilter('date_modify', 'twig_date_modify_filter', ['needs_environment' => true]),
168
+ new TwigFilter('format', 'sprintf'),
169
+ new TwigFilter('replace', 'twig_replace_filter'),
170
+ new TwigFilter('number_format', 'twig_number_format_filter', ['needs_environment' => true]),
171
+ new TwigFilter('abs', 'abs'),
172
+ new TwigFilter('round', 'twig_round'),
173
+
174
+ // encoding
175
+ new TwigFilter('url_encode', 'twig_urlencode_filter'),
176
+ new TwigFilter('json_encode', 'twig_jsonencode_filter'),
177
+ new TwigFilter('convert_encoding', 'twig_convert_encoding'),
178
+
179
+ // string filters
180
+ new TwigFilter('title', 'twig_title_string_filter', ['needs_environment' => true]),
181
+ new TwigFilter('capitalize', 'twig_capitalize_string_filter', ['needs_environment' => true]),
182
+ new TwigFilter('upper', 'strtoupper'),
183
+ new TwigFilter('lower', 'strtolower'),
184
+ new TwigFilter('striptags', 'strip_tags'),
185
+ new TwigFilter('trim', 'twig_trim_filter'),
186
+ new TwigFilter('nl2br', 'nl2br', ['pre_escape' => 'html', 'is_safe' => ['html']]),
187
+ new TwigFilter('spaceless', 'twig_spaceless', ['is_safe' => ['html']]),
188
+
189
+ // array helpers
190
+ new TwigFilter('join', 'twig_join_filter'),
191
+ new TwigFilter('split', 'twig_split_filter', ['needs_environment' => true]),
192
+ new TwigFilter('sort', 'twig_sort_filter'),
193
+ new TwigFilter('merge', 'twig_array_merge'),
194
+ new TwigFilter('batch', 'twig_array_batch'),
195
+
196
+ // string/array filters
197
+ new TwigFilter('reverse', 'twig_reverse_filter', ['needs_environment' => true]),
198
+ new TwigFilter('length', 'twig_length_filter', ['needs_environment' => true]),
199
+ new TwigFilter('slice', 'twig_slice', ['needs_environment' => true]),
200
+ new TwigFilter('first', 'twig_first', ['needs_environment' => true]),
201
+ new TwigFilter('last', 'twig_last', ['needs_environment' => true]),
202
+
203
+ // iteration and runtime
204
+ new TwigFilter('default', '_twig_default_filter', ['node_class' => '\Twig\Node\Expression\Filter\DefaultFilter']),
205
+ new TwigFilter('keys', 'twig_get_array_keys_filter'),
206
+
207
+ // escaping
208
+ new TwigFilter('escape', 'twig_escape_filter', ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']),
209
+ new TwigFilter('e', 'twig_escape_filter', ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']),
210
+ ];
211
+
212
+ if (\function_exists('mb_get_info')) {
213
+ $filters[] = new TwigFilter('upper', 'twig_upper_filter', ['needs_environment' => true]);
214
+ $filters[] = new TwigFilter('lower', 'twig_lower_filter', ['needs_environment' => true]);
215
+ }
216
+
217
+ return $filters;
218
+ }
219
+
220
+ public function getFunctions()
221
+ {
222
+ return [
223
+ new TwigFunction('max', 'max'),
224
+ new TwigFunction('min', 'min'),
225
+ new TwigFunction('range', 'range'),
226
+ new TwigFunction('constant', 'twig_constant'),
227
+ new TwigFunction('cycle', 'twig_cycle'),
228
+ new TwigFunction('random', 'twig_random', ['needs_environment' => true]),
229
+ new TwigFunction('date', 'twig_date_converter', ['needs_environment' => true]),
230
+ new TwigFunction('include', 'twig_include', ['needs_environment' => true, 'needs_context' => true, 'is_safe' => ['all']]),
231
+ new TwigFunction('source', 'twig_source', ['needs_environment' => true, 'is_safe' => ['all']]),
232
+ ];
233
+ }
234
+
235
+ public function getTests()
236
+ {
237
+ return [
238
+ new TwigTest('even', null, ['node_class' => '\Twig\Node\Expression\Test\EvenTest']),
239
+ new TwigTest('odd', null, ['node_class' => '\Twig\Node\Expression\Test\OddTest']),
240
+ new TwigTest('defined', null, ['node_class' => '\Twig\Node\Expression\Test\DefinedTest']),
241
+ new TwigTest('sameas', null, ['node_class' => '\Twig\Node\Expression\Test\SameasTest', 'deprecated' => '1.21', 'alternative' => 'same as']),
242
+ new TwigTest('same as', null, ['node_class' => '\Twig\Node\Expression\Test\SameasTest']),
243
+ new TwigTest('none', null, ['node_class' => '\Twig\Node\Expression\Test\NullTest']),
244
+ new TwigTest('null', null, ['node_class' => '\Twig\Node\Expression\Test\NullTest']),
245
+ new TwigTest('divisibleby', null, ['node_class' => '\Twig\Node\Expression\Test\DivisiblebyTest', 'deprecated' => '1.21', 'alternative' => 'divisible by']),
246
+ new TwigTest('divisible by', null, ['node_class' => '\Twig\Node\Expression\Test\DivisiblebyTest']),
247
+ new TwigTest('constant', null, ['node_class' => '\Twig\Node\Expression\Test\ConstantTest']),
248
+ new TwigTest('empty', 'twig_test_empty'),
249
+ new TwigTest('iterable', 'twig_test_iterable'),
250
+ ];
251
+ }
252
+
253
+ public function getOperators()
254
+ {
255
+ return [
256
+ [
257
+ 'not' => ['precedence' => 50, 'class' => '\Twig\Node\Expression\Unary\NotUnary'],
258
+ '-' => ['precedence' => 500, 'class' => '\Twig\Node\Expression\Unary\NegUnary'],
259
+ '+' => ['precedence' => 500, 'class' => '\Twig\Node\Expression\Unary\PosUnary'],
260
+ ],
261
+ [
262
+ 'or' => ['precedence' => 10, 'class' => '\Twig\Node\Expression\Binary\OrBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
263
+ 'and' => ['precedence' => 15, 'class' => '\Twig\Node\Expression\Binary\AndBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
264
+ 'b-or' => ['precedence' => 16, 'class' => '\Twig\Node\Expression\Binary\BitwiseOrBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
265
+ 'b-xor' => ['precedence' => 17, 'class' => '\Twig\Node\Expression\Binary\BitwiseXorBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
266
+ 'b-and' => ['precedence' => 18, 'class' => '\Twig\Node\Expression\Binary\BitwiseAndBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
267
+ '==' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\EqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
268
+ '!=' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\NotEqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
269
+ '<' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\LessBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
270
+ '>' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\GreaterBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
271
+ '>=' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\GreaterEqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
272
+ '<=' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\LessEqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
273
+ 'not in' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\NotInBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
274
+ 'in' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\InBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
275
+ 'matches' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\MatchesBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
276
+ 'starts with' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\StartsWithBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
277
+ 'ends with' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\EndsWithBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
278
+ '..' => ['precedence' => 25, 'class' => '\Twig\Node\Expression\Binary\RangeBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
279
+ '+' => ['precedence' => 30, 'class' => '\Twig\Node\Expression\Binary\AddBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
280
+ '-' => ['precedence' => 30, 'class' => '\Twig\Node\Expression\Binary\SubBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
281
+ '~' => ['precedence' => 40, 'class' => '\Twig\Node\Expression\Binary\ConcatBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
282
+ '*' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\MulBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
283
+ '/' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\DivBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
284
+ '//' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\FloorDivBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
285
+ '%' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\ModBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
286
+ 'is' => ['precedence' => 100, 'associativity' => ExpressionParser::OPERATOR_LEFT],
287
+ 'is not' => ['precedence' => 100, 'associativity' => ExpressionParser::OPERATOR_LEFT],
288
+ '**' => ['precedence' => 200, 'class' => '\Twig\Node\Expression\Binary\PowerBinary', 'associativity' => ExpressionParser::OPERATOR_RIGHT],
289
+ '??' => ['precedence' => 300, 'class' => '\Twig\Node\Expression\NullCoalesceExpression', 'associativity' => ExpressionParser::OPERATOR_RIGHT],
290
+ ],
291
+ ];
292
+ }
293
+
294
+ public function getName()
295
+ {
296
+ return 'core';
297
+ }
298
+ }
299
+
300
+ class_alias('Twig\Extension\CoreExtension', 'Twig_Extension_Core');
301
+ }
302
+
303
+ namespace {
304
+ use Twig\Environment;
305
+ use Twig\Error\LoaderError;
306
+ use Twig\Error\RuntimeError;
307
+ use Twig\Loader\SourceContextLoaderInterface;
308
+ use Twig\Markup;
309
+ use Twig\Node\Expression\ConstantExpression;
310
+ use Twig\Node\Node;
311
+
312
+ /**
313
+ * Cycles over a value.
314
+ *
315
+ * @param \ArrayAccess|array $values
316
+ * @param int $position The cycle position
317
+ *
318
+ * @return string The next value in the cycle
319
+ */
320
+ function twig_cycle($values, $position)
321
+ {
322
+ if (!\is_array($values) && !$values instanceof \ArrayAccess) {
323
+ return $values;
324
+ }
325
+
326
+ return $values[$position % \count($values)];
327
+ }
328
+
329
+ /**
330
+ * Returns a random value depending on the supplied parameter type:
331
+ * - a random item from a \Traversable or array
332
+ * - a random character from a string
333
+ * - a random integer between 0 and the integer parameter.
334
+ *
335
+ * @param \Traversable|array|int|float|string $values The values to pick a random item from
336
+ * @param int|null $max Maximum value used when $values is an int
337
+ *
338
+ * @throws RuntimeError when $values is an empty array (does not apply to an empty string which is returned as is)
339
+ *
340
+ * @return mixed A random value from the given sequence
341
+ */
342
+ function twig_random(Environment $env, $values = null, $max = null)
343
+ {
344
+ if (null === $values) {
345
+ return null === $max ? mt_rand() : mt_rand(0, $max);
346
+ }
347
+
348
+ if (\is_int($values) || \is_float($values)) {
349
+ if (null === $max) {
350
+ if ($values < 0) {
351
+ $max = 0;
352
+ $min = $values;
353
+ } else {
354
+ $max = $values;
355
+ $min = 0;
356
+ }
357
+ } else {
358
+ $min = $values;
359
+ $max = $max;
360
+ }
361
+
362
+ return mt_rand($min, $max);
363
+ }
364
+
365
+ if (\is_string($values)) {
366
+ if ('' === $values) {
367
+ return '';
368
+ }
369
+ if (null !== $charset = $env->getCharset()) {
370
+ if ('UTF-8' !== $charset) {
371
+ $values = twig_convert_encoding($values, 'UTF-8', $charset);
372
+ }
373
+
374
+ // unicode version of str_split()
375
+ // split at all positions, but not after the start and not before the end
376
+ $values = preg_split('/(?<!^)(?!$)/u', $values);
377
+
378
+ if ('UTF-8' !== $charset) {
379
+ foreach ($values as $i => $value) {
380
+ $values[$i] = twig_convert_encoding($value, $charset, 'UTF-8');
381
+ }
382
+ }
383
+ } else {
384
+ return $values[mt_rand(0, \strlen($values) - 1)];
385
+ }
386
+ }
387
+
388
+ if (!twig_test_iterable($values)) {
389
+ return $values;
390
+ }
391
+
392
+ $values = twig_to_array($values);
393
+
394
+ if (0 === \count($values)) {
395
+ throw new RuntimeError('The random function cannot pick from an empty array.');
396
+ }
397
+
398
+ return $values[array_rand($values, 1)];
399
+ }
400
+
401
+ /**
402
+ * Converts a date to the given format.
403
+ *
404
+ * {{ post.published_at|date("m/d/Y") }}
405
+ *
406
+ * @param \DateTime|\DateTimeInterface|\DateInterval|string $date A date
407
+ * @param string|null $format The target format, null to use the default
408
+ * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged
409
+ *
410
+ * @return string The formatted date
411
+ */
412
+ function twig_date_format_filter(Environment $env, $date, $format = null, $timezone = null)
413
+ {
414
+ if (null === $format) {
415
+ $formats = $env->getExtension('\Twig\Extension\CoreExtension')->getDateFormat();
416
+ $format = $date instanceof \DateInterval ? $formats[1] : $formats[0];
417
+ }
418
+
419
+ if ($date instanceof \DateInterval) {
420
+ return $date->format($format);
421
+ }
422
+
423
+ return twig_date_converter($env, $date, $timezone)->format($format);
424
+ }
425
+
426
+ /**
427
+ * Returns a new date object modified.
428
+ *
429
+ * {{ post.published_at|date_modify("-1day")|date("m/d/Y") }}
430
+ *
431
+ * @param \DateTime|string $date A date
432
+ * @param string $modifier A modifier string
433
+ *
434
+ * @return \DateTime
435
+ */
436
+ function twig_date_modify_filter(Environment $env, $date, $modifier)
437
+ {
438
+ $date = twig_date_converter($env, $date, false);
439
+ $resultDate = $date->modify($modifier);
440
+
441
+ // This is a hack to ensure PHP 5.2 support and support for \DateTimeImmutable
442
+ // \DateTime::modify does not return the modified \DateTime object < 5.3.0
443
+ // and \DateTimeImmutable does not modify $date.
444
+ return null === $resultDate ? $date : $resultDate;
445
+ }
446
+
447
+ /**
448
+ * Converts an input to a \DateTime instance.
449
+ *
450
+ * {% if date(user.created_at) < date('+2days') %}
451
+ * {# do something #}
452
+ * {% endif %}
453
+ *
454
+ * @param \DateTime|\DateTimeInterface|string|null $date A date
455
+ * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged
456
+ *
457
+ * @return \DateTime
458
+ */
459
+ function twig_date_converter(Environment $env, $date = null, $timezone = null)
460
+ {
461
+ // determine the timezone
462
+ if (false !== $timezone) {
463
+ if (null === $timezone) {
464
+ $timezone = $env->getExtension('\Twig\Extension\CoreExtension')->getTimezone();
465
+ } elseif (!$timezone instanceof \DateTimeZone) {
466
+ $timezone = new \DateTimeZone($timezone);
467
+ }
468
+ }
469
+
470
+ // immutable dates
471
+ if ($date instanceof \DateTimeImmutable) {
472
+ return false !== $timezone ? $date->setTimezone($timezone) : $date;
473
+ }
474
+
475
+ if ($date instanceof \DateTime || $date instanceof \DateTimeInterface) {
476
+ $date = clone $date;
477
+ if (false !== $timezone) {
478
+ $date->setTimezone($timezone);
479
+ }
480
+
481
+ return $date;
482
+ }
483
+
484
+ if (null === $date || 'now' === $date) {
485
+ return new \DateTime($date, false !== $timezone ? $timezone : $env->getExtension('\Twig\Extension\CoreExtension')->getTimezone());
486
+ }
487
+
488
+ $asString = (string) $date;
489
+ if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) {
490
+ $date = new \DateTime('@'.$date);
491
+ } else {
492
+ $date = new \DateTime($date, $env->getExtension('\Twig\Extension\CoreExtension')->getTimezone());
493
+ }
494
+
495
+ if (false !== $timezone) {
496
+ $date->setTimezone($timezone);
497
+ }
498
+
499
+ return $date;
500
+ }
501
+
502
+ /**
503
+ * Replaces strings within a string.
504
+ *
505
+ * @param string $str String to replace in
506
+ * @param array|\Traversable $from Replace values
507
+ * @param string|null $to Replace to, deprecated (@see https://secure.php.net/manual/en/function.strtr.php)
508
+ *
509
+ * @return string
510
+ */
511
+ function twig_replace_filter($str, $from, $to = null)
512
+ {
513
+ if (\is_string($from) && \is_string($to)) {
514
+ @trigger_error('Using "replace" with character by character replacement is deprecated since version 1.22 and will be removed in Twig 2.0', E_USER_DEPRECATED);
515
+
516
+ return strtr($str, $from, $to);
517
+ } elseif (!twig_test_iterable($from)) {
518
+ throw new RuntimeError(sprintf('The "replace" filter expects an array or "Traversable" as replace values, got "%s".', \is_object($from) ? \get_class($from) : \gettype($from)));
519
  }
520
+
521
+ return strtr($str, twig_to_array($from));
522
+ }
523
+
524
+ /**
525
+ * Rounds a number.
526
+ *
527
+ * @param int|float $value The value to round
528
+ * @param int|float $precision The rounding precision
529
+ * @param string $method The method to use for rounding
530
+ *
531
+ * @return int|float The rounded number
532
+ */
533
+ function twig_round($value, $precision = 0, $method = 'common')
534
+ {
535
+ if ('common' == $method) {
536
+ return round($value, $precision);
537
+ }
538
+
539
+ if ('ceil' != $method && 'floor' != $method) {
540
+ throw new RuntimeError('The round filter only supports the "common", "ceil", and "floor" methods.');
541
+ }
542
+
543
+ return $method($value * pow(10, $precision)) / pow(10, $precision);
544
+ }
545
+
546
+ /**
547
+ * Number format filter.
548
+ *
549
+ * All of the formatting options can be left null, in that case the defaults will
550
+ * be used. Supplying any of the parameters will override the defaults set in the
551
+ * environment object.
552
+ *
553
+ * @param mixed $number A float/int/string of the number to format
554
+ * @param int $decimal the number of decimal points to display
555
+ * @param string $decimalPoint the character(s) to use for the decimal point
556
+ * @param string $thousandSep the character(s) to use for the thousands separator
557
+ *
558
+ * @return string The formatted number
559
+ */
560
+ function twig_number_format_filter(Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null)
561
+ {
562
+ $defaults = $env->getExtension('\Twig\Extension\CoreExtension')->getNumberFormat();
563
+ if (null === $decimal) {
564
+ $decimal = $defaults[0];
565
+ }
566
+
567
+ if (null === $decimalPoint) {
568
+ $decimalPoint = $defaults[1];
569
+ }
570
+
571
+ if (null === $thousandSep) {
572
+ $thousandSep = $defaults[2];
573
+ }
574
+
575
+ return number_format((float) $number, $decimal, $decimalPoint, $thousandSep);
576
+ }
577
+
578
+ /**
579
+ * URL encodes (RFC 3986) a string as a path segment or an array as a query string.
580
+ *
581
+ * @param string|array $url A URL or an array of query parameters
582
+ *
583
+ * @return string The URL encoded value
584
+ */
585
+ function twig_urlencode_filter($url)
586
+ {
587
+ if (\is_array($url)) {
588
+ if (\defined('PHP_QUERY_RFC3986')) {
589
+ return http_build_query($url, '', '&', PHP_QUERY_RFC3986);
590
+ }
591
+
592
+ return http_build_query($url, '', '&');
593
+ }
594
+
595
+ return rawurlencode($url);
596
+ }
597
+
598
+ /**
599
+ * JSON encodes a variable.
600
+ *
601
+ * @param mixed $value the value to encode
602
+ * @param int $options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_AP