Version Description
(2019-02-27) = * Added a modal with an optional poll when the plugin is deactivated. * Improved the core plugin's on-boarding process for brand new users. * Fixed the "Sorted" error appearing constantly in the debug log. * The timeout for the truncating posts hook has been extended. * Fixed PHP warnings appearing on WordPress multisite. * Fixed PHP notice appearing on Feed Items page. * Fixed strict standards notice appearing on settings import.
Download this release
Release Info
Developer | markzahra |
Plugin | WP RSS Aggregator |
Version | 4.12.1 |
Comparing to | |
See all releases |
Code changes from version 4.12 to 4.12.1
- css/beacon.css +9 -0
- css/intro.min.css +1 -1
- css/plugins.min.css +1 -0
- css/src/intro/steps.scss +16 -5
- css/src/plugins/form.scss +48 -0
- css/src/plugins/index.scss +25 -0
- css/src/plugins/modal.scss +173 -0
- css/src/update/index.scss +83 -0
- css/update.min.css +1 -0
- images/light-line-logo.png +0 -0
- images/wp-rss-aggregator-support-beacon.png +0 -0
- includes/Aventura/Wprss/Core/Licensing/Manager.php +1 -1
- includes/Aventura/Wprss/Core/Model/BulkSourceImport/ArrayImporter.php +5 -5
- includes/Aventura/Wprss/Core/Model/Regex/AbstractRegex.php +4 -3
- includes/admin-activate.php +38 -0
- includes/admin-addons.php +0 -2
- includes/admin-ajax-notice.php +3 -1
- includes/admin-debugging.php +3 -3
- includes/admin-help.php +48 -2
- includes/admin-import-export.php +1 -3
- includes/{admin-intro.php → admin-intro-page.php} +44 -66
- includes/admin-options.php +0 -2
- includes/admin-plugins.php +117 -0
- includes/admin-update-page.php +133 -0
- includes/admin.php +43 -0
- includes/custom-feed.php +3 -7
- includes/custom-post-types.php +2 -1
- includes/feed-importing.php +0 -2
- includes/licensing.php +33 -0
- includes/opml-importer.php +3 -3
- includes/roles-capabilities.php +2 -2
- includes/scripts.php +13 -0
- includes/secure-reset.php +3 -1
- includes/twig.php +2 -2
- js/beacon.min.js +5 -0
- js/intro.min.js +1 -6
- js/plugins.min.js +1 -0
- js/src/intro/Wizard.vue +58 -20
- js/src/intro/copy.js +37 -0
- js/src/plugins/Modal.vue +114 -0
- js/src/plugins/PluginDisablePoll.vue +112 -0
- js/src/plugins/SerializedForm.vue +89 -0
- js/src/plugins/index.js +10 -0
- js/update.min.js +1 -0
- js/wpra-manifest.min.js +1 -0
- js/wpra-vendor.min.js +12 -0
- readme.txt +78 -64
- templates/admin-update-page.twig +76 -0
- vendor/autoload.php +1 -1
- vendor/composer/ClassLoader.php +2 -2
- vendor/composer/autoload_real.php +7 -7
- vendor/composer/autoload_static.php +4 -4
- vendor/composer/installed.json +13 -13
- vendor/symfony/polyfill-ctype/LICENSE +1 -1
- vendor/symfony/polyfill-ctype/composer.json +1 -1
- vendor/twig/twig/.php_cs.dist +4 -2
- vendor/twig/twig/.travis.yml +0 -1
- vendor/twig/twig/CHANGELOG +2 -2
- vendor/twig/twig/composer.json +1 -4
- vendor/twig/twig/doc/advanced.rst +127 -88
- vendor/twig/twig/doc/advanced_legacy.rst +45 -45
- vendor/twig/twig/doc/api.rst +55 -55
- vendor/twig/twig/doc/deprecated.rst +54 -54
- vendor/twig/twig/doc/filters/date.rst +4 -4
- vendor/twig/twig/doc/filters/escape.rst +2 -2
- vendor/twig/twig/doc/filters/join.rst +2 -2
- vendor/twig/twig/doc/filters/number_format.rst +2 -2
- vendor/twig/twig/doc/functions/date.rst +2 -2
- vendor/twig/twig/doc/functions/dump.rst +3 -3
- vendor/twig/twig/doc/functions/include.rst +2 -2
- vendor/twig/twig/doc/functions/template_from_string.rst +3 -3
- vendor/twig/twig/doc/installation.rst +1 -1
- vendor/twig/twig/doc/internals.rst +24 -24
- vendor/twig/twig/doc/intro.rst +6 -6
- vendor/twig/twig/doc/recipes.rst +35 -35
- vendor/twig/twig/doc/tags/extends.rst +1 -1
- vendor/twig/twig/doc/tags/filter.rst +2 -2
- vendor/twig/twig/doc/tags/include.rst +27 -3
- vendor/twig/twig/doc/tags/set.rst +1 -1
- vendor/twig/twig/doc/templates.rst +3 -1
- vendor/twig/twig/ext/twig/php_twig.h +1 -1
- vendor/twig/twig/ext/twig/twig.c +14 -14
- vendor/twig/twig/lib/Twig/Autoloader.php +1 -1
- vendor/twig/twig/lib/Twig/BaseNodeVisitor.php +15 -11
- vendor/twig/twig/lib/Twig/Cache/Filesystem.php +11 -9
- vendor/twig/twig/lib/Twig/Cache/Null.php +3 -1
- vendor/twig/twig/lib/Twig/Compiler.php +14 -12
- vendor/twig/twig/lib/Twig/ContainerRuntimeLoader.php +2 -1
- vendor/twig/twig/lib/Twig/Environment.php +205 -176
- vendor/twig/twig/lib/Twig/Error.php +18 -15
- vendor/twig/twig/lib/Twig/Error/Loader.php +7 -5
- vendor/twig/twig/lib/Twig/Error/Runtime.php +3 -1
- vendor/twig/twig/lib/Twig/Error/Syntax.php +5 -3
- vendor/twig/twig/lib/Twig/ExpressionParser.php +163 -139
- vendor/twig/twig/lib/Twig/Extension.php +6 -3
- vendor/twig/twig/lib/Twig/Extension/Core.php +328 -338
- vendor/twig/twig/lib/Twig/Extension/Debug.php +9 -5
- vendor/twig/twig/lib/Twig/Extension/Escaper.php +12 -7
- vendor/twig/twig/lib/Twig/Extension/GlobalsInterface.php +1 -1
- vendor/twig/twig/lib/Twig/Extension/InitRuntimeInterface.php +1 -1
- vendor/twig/twig/lib/Twig/Extension/Optimizer.php +5 -2
- vendor/twig/twig/lib/Twig/Extension/Profiler.php +10 -6
- vendor/twig/twig/lib/Twig/Extension/Sandbox.php +11 -6
- vendor/twig/twig/lib/Twig/Extension/Staging.php +7 -3
- vendor/twig/twig/lib/Twig/Extension/StringLoader.php +9 -8
- vendor/twig/twig/lib/Twig/ExtensionInterface.php +13 -6
- vendor/twig/twig/lib/Twig/FactoryRuntimeLoader.php +3 -1
- vendor/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php +1 -1
- vendor/twig/twig/lib/Twig/Filter.php +4 -2
- vendor/twig/twig/lib/Twig/Filter/Method.php +4 -2
- vendor/twig/twig/lib/Twig/FilterInterface.php +3 -1
- vendor/twig/twig/lib/Twig/Function.php +4 -2
- vendor/twig/twig/lib/Twig/Function/Method.php +4 -2
- vendor/twig/twig/lib/Twig/FunctionInterface.php +3 -1
- vendor/twig/twig/lib/Twig/Lexer.php +45 -39
- vendor/twig/twig/lib/Twig/LexerInterface.php +8 -4
- vendor/twig/twig/lib/Twig/Loader/Array.php +11 -7
- vendor/twig/twig/lib/Twig/Loader/Chain.php +29 -23
- vendor/twig/twig/lib/Twig/Loader/Filesystem.php +25 -21
- vendor/twig/twig/lib/Twig/Loader/String.php +7 -4
- vendor/twig/twig/lib/Twig/LoaderInterface.php +5 -3
- vendor/twig/twig/lib/Twig/Markup.php +2 -2
- vendor/twig/twig/lib/Twig/Node.php +20 -17
- vendor/twig/twig/lib/Twig/Node/AutoEscape.php +5 -2
- vendor/twig/twig/lib/Twig/Node/Block.php +5 -2
- vendor/twig/twig/lib/Twig/Node/BlockReference.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Body.php +3 -1
- vendor/twig/twig/lib/Twig/Node/CheckSecurity.php +11 -8
- vendor/twig/twig/lib/Twig/Node/Deprecated.php +9 -4
- vendor/twig/twig/lib/Twig/Node/Do.php +7 -3
- vendor/twig/twig/lib/Twig/Node/Embed.php +9 -4
- vendor/twig/twig/lib/Twig/Node/Expression.php +3 -1
- vendor/twig/twig/lib/Twig/Node/Expression/Array.php +11 -6
- vendor/twig/twig/lib/Twig/Node/Expression/AssignName.php +5 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary.php +7 -3
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/Add.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/And.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/Concat.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/Div.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php +7 -3
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/Equal.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php +7 -3
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/Greater.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/In.php +7 -3
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/Less.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/LessEqual.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php +7 -3
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mod.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mul.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotEqual.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php +7 -3
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/Or.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/Power.php +7 -3
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/Range.php +7 -3
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php +7 -3
- vendor/twig/twig/lib/Twig/Node/Expression/Binary/Sub.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.php +10 -6
- vendor/twig/twig/lib/Twig/Node/Expression/Call.php +43 -34
- vendor/twig/twig/lib/Twig/Node/Expression/Conditional.php +7 -3
- vendor/twig/twig/lib/Twig/Node/Expression/Constant.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php +5 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Filter.php +11 -5
- vendor/twig/twig/lib/Twig/Node/Expression/Filter/Default.php +17 -10
- vendor/twig/twig/lib/Twig/Node/Expression/Function.php +9 -4
- vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php +10 -5
- vendor/twig/twig/lib/Twig/Node/Expression/MethodCall.php +10 -4
- vendor/twig/twig/lib/Twig/Node/Expression/Name.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/NullCoalesce.php +16 -6
- vendor/twig/twig/lib/Twig/Node/Expression/Parent.php +5 -2
- vendor/twig/twig/lib/Twig/Node/Expression/TempName.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Test.php +10 -5
- vendor/twig/twig/lib/Twig/Node/Expression/Test/Constant.php +8 -7
- vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.php +25 -17
- vendor/twig/twig/lib/Twig/Node/Expression/Test/Divisibleby.php +5 -4
- vendor/twig/twig/lib/Twig/Node/Expression/Test/Even.php +5 -4
- vendor/twig/twig/lib/Twig/Node/Expression/Test/Null.php +5 -4
- vendor/twig/twig/lib/Twig/Node/Expression/Test/Odd.php +5 -4
- vendor/twig/twig/lib/Twig/Node/Expression/Test/Sameas.php +5 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Unary.php +7 -3
- vendor/twig/twig/lib/Twig/Node/Expression/Unary/Neg.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Unary/Not.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Expression/Unary/Pos.php +6 -2
- vendor/twig/twig/lib/Twig/Node/Flush.php +5 -2
- vendor/twig/twig/lib/Twig/Node/For.php +13 -6
- vendor/twig/twig/lib/Twig/Node/ForLoop.php +5 -2
- vendor/twig/twig/lib/Twig/Node/If.php +6 -3
- vendor/twig/twig/lib/Twig/Node/Import.php +9 -4
- vendor/twig/twig/lib/Twig/Node/Include.php +11 -6
- vendor/twig/twig/lib/Twig/Node/Macro.php +11 -7
- vendor/twig/twig/lib/Twig/Node/Module.php +70 -45
- vendor/twig/twig/lib/Twig/Node/Print.php +8 -3
- vendor/twig/twig/lib/Twig/Node/Sandbox.php +6 -3
- vendor/twig/twig/lib/Twig/Node/SandboxedPrint.php +11 -6
- vendor/twig/twig/lib/Twig/Node/Set.php +15 -9
- vendor/twig/twig/lib/Twig/Node/SetTemp.php +5 -2
- vendor/twig/twig/lib/Twig/Node/Spaceless.php +5 -2
- vendor/twig/twig/lib/Twig/Node/Text.php +6 -2
- vendor/twig/twig/lib/Twig/Node/With.php +7 -4
- vendor/twig/twig/lib/Twig/NodeInterface.php +4 -2
- vendor/twig/twig/lib/Twig/NodeTraverser.php +7 -5
- vendor/twig/twig/lib/Twig/NodeVisitor/Escaper.php +39 -25
- vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php +55 -36
- vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php +28 -15
- vendor/twig/twig/lib/Twig/NodeVisitor/Sandbox.php +22 -11
- vendor/twig/twig/lib/Twig/NodeVisitorInterface.php +4 -2
- vendor/twig/twig/lib/Twig/Parser.php +65 -45
- vendor/twig/twig/lib/Twig/ParserInterface.php +7 -3
- vendor/twig/twig/lib/Twig/Profiler/Dumper/Base.php +8 -6
- vendor/twig/twig/lib/Twig/Profiler/Dumper/Blackfire.php +5 -3
- vendor/twig/twig/lib/Twig/Profiler/Dumper/Html.php +8 -5
- vendor/twig/twig/lib/Twig/Profiler/Dumper/Text.php +7 -4
- vendor/twig/twig/lib/Twig/Profiler/Node/EnterProfile.php +6 -3
- vendor/twig/twig/lib/Twig/Profiler/Node/LeaveProfile.php +5 -2
- vendor/twig/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php +25 -14
- vendor/twig/twig/lib/Twig/Profiler/Profile.php +2 -2
- vendor/twig/twig/lib/Twig/Sandbox/SecurityError.php +3 -1
- vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php +4 -2
- vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php +4 -2
- vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedMethodError.php +4 -2
- vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedPropertyError.php +4 -2
- vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php +4 -2
- vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php +23 -15
- vendor/twig/twig/lib/Twig/SimpleFilter.php +5 -3
- vendor/twig/twig/lib/Twig/SimpleFunction.php +5 -3
- vendor/twig/twig/lib/Twig/SimpleTest.php +1 -1
- vendor/twig/twig/lib/Twig/SourceContextLoaderInterface.php +5 -2
- vendor/twig/twig/lib/Twig/Template.php +58 -50
- vendor/twig/twig/lib/Twig/TemplateInterface.php +3 -1
- vendor/twig/twig/lib/Twig/TemplateWrapper.php +11 -7
- vendor/twig/twig/lib/Twig/Test/IntegrationTestCase.php +30 -20
- vendor/twig/twig/lib/Twig/Test/Method.php +4 -2
- vendor/twig/twig/lib/Twig/Test/NodeTestCase.php +9 -5
- vendor/twig/twig/lib/Twig/Token.php +5 -5
- vendor/twig/twig/lib/Twig/TokenParser.php +5 -2
- vendor/twig/twig/lib/Twig/TokenParser/AutoEscape.php +27 -23
- vendor/twig/twig/lib/Twig/TokenParser/Block.php +21 -15
- vendor/twig/twig/lib/Twig/TokenParser/Deprecated.php +10 -9
- vendor/twig/twig/lib/Twig/TokenParser/Do.php +8 -4
- vendor/twig/twig/lib/Twig/TokenParser/Embed.php +19 -13
- vendor/twig/twig/lib/Twig/TokenParser/Extends.php +9 -7
- vendor/twig/twig/lib/Twig/TokenParser/Filter.php +18 -13
- vendor/twig/twig/lib/Twig/TokenParser/Flush.php +8 -4
- vendor/twig/twig/lib/Twig/TokenParser/For.php +38 -30
- vendor/twig/twig/lib/Twig/TokenParser/From.php +14 -10
- vendor/twig/twig/lib/Twig/TokenParser/If.php +23 -19
- vendor/twig/twig/lib/Twig/TokenParser/Import.php +10 -7
- vendor/twig/twig/lib/Twig/TokenParser/Include.php +12 -10
- vendor/twig/twig/lib/Twig/TokenParser/Macro.php +18 -14
- vendor/twig/twig/lib/Twig/TokenParser/Sandbox.php +20 -15
- vendor/twig/twig/lib/Twig/TokenParser/Set.php +17 -19
- vendor/twig/twig/lib/Twig/TokenParser/Spaceless.php +13 -12
- vendor/twig/twig/lib/Twig/TokenParser/Use.php +21 -17
- vendor/twig/twig/lib/Twig/TokenParser/With.php +12 -8
- vendor/twig/twig/lib/Twig/TokenParserBroker.php +11 -9
- vendor/twig/twig/lib/Twig/TokenParserBrokerInterface.php +4 -2
- vendor/twig/twig/lib/Twig/TokenParserInterface.php +7 -3
- vendor/twig/twig/lib/Twig/TokenStream.php +19 -15
- vendor/twig/twig/lib/Twig/Util/DeprecationCollector.php +14 -9
- vendor/twig/twig/test/Twig/Tests/Cache/FilesystemTest.php +13 -11
- vendor/twig/twig/test/Twig/Tests/CompilerTest.php +4 -1
- vendor/twig/twig/test/Twig/Tests/ContainerRuntimeLoaderTest.php +5 -3
- vendor/twig/twig/test/Twig/Tests/CustomExtensionTest.php +8 -5
- vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php +93 -76
- vendor/twig/twig/test/Twig/Tests/ErrorTest.php +14 -7
css/beacon.css
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#HSBeaconFabButton {
|
2 |
+
bottom: 16px !important;
|
3 |
+
right: 20px !important;
|
4 |
+
}
|
5 |
+
|
6 |
+
#HSBeaconContainerFrame {
|
7 |
+
bottom: 86px !important;
|
8 |
+
right: 20px !important;
|
9 |
+
}
|
css/intro.min.css
CHANGED
@@ -1 +1 @@
|
|
1 |
-
.wrpa-expander{will-change:height;transform:translateZ(0);backface-visibility:hidden;perspective:1000px}.expand-enter-active,.expand-leave-active{transition:height .35s ease;overflow:hidden}.expand-enter,.expand-leave-to{height:0}.fade-enter,.fade-leave-to{opacity:0}.fade-enter-active,.fade-leave-active{transition:opacity .3s ease}.slide-up-enter{transform:translateY(10px);opacity:0}.slide-up-leave-to{transform:translateY(-10px);opacity:0}.slide-up-enter-active,.slide-up-leave-active{transition:all .3s ease}.slide-down-enter{transform:translateY(-10px);opacity:0}.slide-down-leave-to{transform:translateY(10px);opacity:0}.slide-down-enter-active,.slide-down-leave-active{transition:all .3s ease}.wpra-expander__title{cursor:pointer;user-select:none}.wpra-expander__title span{opacity:.5;vertical-align:bottom;transition:transform .3s ease}.wpra-expander__content{padding:0 .5rem;opacity:0;transition:opacity .3s ease}.wpra-expander--expanded .wpra-expander__content{opacity:1}.wpra-expander--expanded .wpra-expander__title span{transform:rotate(180deg)}[v-cloak] .vcloak--visible{display:block}[v-cloak] .vcloak--hidden{display:none}.vcloak--visible{min-height:60px;display:none}.loading-container{position:relative}.loading-container:before{display:block;content:"";position:absolute;left:calc(50% - 20px);top:calc(50% - 20px);box-sizing:border-box;height:40px;width:40px;border:0 solid #d0d0d0;border-radius:50%;box-shadow:inset 0 -12px 0 16px #d0d0d0;animation:rotate 1s infinite linear;z-index:3}.loading-container:after{display:block;content:"";position:absolute;z-index:2;background-color:hsla(0,0%,95%,.5);width:100%;height:100%;left:0;top:0}.loading-container--white:after{background-color:#fff}.loading-button{pointer-events:none;position:relative}.loading-button:before{display:block;content:"";position:absolute;left:calc(50% - 8px);top:calc(50% - 8px);box-sizing:border-box;height:16px;width:16px;border:0 solid #fff;border-radius:50%;box-shadow:inset 0 -4px 0 6px #fff;animation:rotate 1s infinite linear;z-index:3}.loading-button:after{display:block;content:"";position:absolute;z-index:2;background-color:inherit;width:100%;height:100%;left:0;top:0}.button-default.loading-button:before{box-shadow:inset 0 -4px 0 6px #6f6f6f}.loading-inline{display:inline-block;pointer-events:none;position:relative}.loading-inline:before{display:block;content:"";position:absolute;left:calc(50% + 1px);top:calc(50% - 11px);box-sizing:border-box;height:14px;width:14px;border:0 solid #d0d0d0;border-radius:50%;box-shadow:inset 0 -3px 0 5px #d0d0d0;animation:rotate 1s infinite linear;z-index:3}.loading-inline:after{display:block;content:"";position:absolute;z-index:2;background-color:inherit;width:100%;height:100%;left:0;top:0}@keyframes rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.wpra-wizard-head{display:flex;padding-bottom:1.5rem;padding-top:.75rem}.wpra-wizard-head__logo{flex-shrink:0}.wpra-wizard-head__logo img{width:57px}.wpra-wizard-head__copy{flex-grow:1;padding-left:1rem;display:flex;flex-direction:column;justify-content:center}.wpra-wizard-head__title{font-size:1.25rem;font-weight:500;padding-bottom:12px}.wpra-wizard-head__subtitle{font-size:1rem;opacity:.85}.wpra-cols{display:flex;margin:0 -.5rem;border-top:2px solid rgba(0,0,0,.05);padding-top:1.45rem}.wpra-cols-title{font-weight:400;font-size:1rem;padding-bottom:1rem}@media (max-width:50em){.wpra-cols{flex-wrap:wrap}}.wpra-cols .col{flex-basis:50%;padding:0 .5rem}@media (max-width:50em){.wpra-cols .col{flex-basis:100%;padding-bottom:1rem}}.wpra-cols .col img{max-width:100%}.wpra-cols .col p{font-size:14px;line-height:1.6}.wpra-cols .col p:first-child{margin-top:0}.wpra-feed-input{width:26rem;padding:6px 10px;max-width:100%}.wpra-feedback{display:flex}.wpra-feedback__photo{flex-shrink:0}.wpra-feedback__photo img{width:70px;border-radius:100%}.wpra-feedback__copy{padding-left:.5rem;flex-grow:1}.wpra-feedback__text{font-size:1rem;font-family:Georgia,serif;font-style:italic;line-height:1.5}.wpra-feedback__rating{padding:.25rem 0 .45rem}.wpra-feedback__rating span{color:#f8ca29}.wpra-feedback__by{opacity:.85}.wpra-feedback__by a{color:#617181}.wpra-demo-photo{margin-bottom:1rem;border-radius:4px;border:1px solid rgba(0,0,0,.15)}.wpra-feed-items{padding-left:.5rem;margin-bottom:1rem;border-left:4px solid #ff792b}.wpra-feed-items .wpra-feed-item{padding:.75rem}.wpra-feed-items .wpra-feed-item__link{padding-bottom:4px}.step-items{display:flex;position:relative;flex-direction:column;align-items:flex-end}.step-items .step-progress{position:absolute;width:3px;height:0;background-color:#00b479;left:17.5px;top:0;transition:height .3s ease;z-index:-1}.step-items .step-progress--1{height:50%}.step-items .step-progress--2{height:100%}@media (max-width:50em){.step-items .step-progress{display:none}}@media (max-width:50em){.step-items{padding:.625rem;flex-direction:row;align-items:flex-start}}.step-items .step-item{font-size:16px;width:15rem;margin-bottom:2.25rem;display:flex;background-color:#f1f1f1}.step-items .step-item:last-child{margin-bottom:0}@media (max-width:50em){.step-items .step-item{flex-direction:column;margin-bottom:0;align-items:center}}.step-items .step-item_active,.step-items .step-item_active .step-item__info,.step-items .step-item_active .step-item__status{opacity:1}@media (max-width:50em){.step-items .step-item_active{flex-grow:1}}.step-items .step-item__description{font-size:14px}.step-items .step-item__info{display:flex;align-items:center;padding-left:.75rem;opacity:.5}@media (max-width:50em){.step-items .step-item__info{padding-left:0;padding-top:.3rem;display:none}}.step-items .step-item__status{width:35px;height:35px;border-radius:50%;border:2px dashed rgba(0,0,0,.5);flex-shrink:0;opacity:.5;text-align:center;font-size:1.25rem;line-height:2.375rem;color:#00b479}.step-items .step-item__status span{display:block;margin:0!important;width:100%;line-height:35px;font-size:26px}.step-items .step-item_completed{opacity:1}.step-items .step-item_completed .step-item__status{border-style:solid;border-color:#00b479;opacity:1}.step-items .step-item_completed .step-item__status span{position:relative}.step-items .step-item_completed .step-item__info{opacity:.5}.wizard{width:100%;margin-left:1rem}@media (max-width:50em){.wizard{margin-left:0}}.wizard ol{margin-left:1.5rem;line-height:1.5;font-size:13px}.wizard ol ul{margin-bottom:1rem}.wizard .form-group{display:flex;align-items:center}@media (max-width:50em){.wizard .form-group{display:block;align-items:unset}.wizard .form-group input{margin-bottom:8px}}.wizard .form-group input{flex-shrink:0}.wizard .form-group .warning-icon{padding-left:4px;color:#ee5a65}.wizard .form-group a{flex-shrink:0;margin-left:6px}.wizard .button-clear{background-color:transparent;border:none;cursor:pointer;height:30px;line-height:28px;padding:0 12px 2px;vertical-align:baseline;opacity:.55}.wizard .button-clear:hover{opacity:.8}.wizard .button{vertical-align:baseline!important}.wizard .pad{display:flex}.wizard .pad-item--grow{flex-grow:1}.wizard .pad-item--no-shrink{flex-shrink:0}.wizard .wpra-success{padding-right:1rem;font-size:14px}.wizard_content{padding:1rem;font-size:14px;max-width:42rem;min-height:16rem;padding-top:12px}@media (max-width:50em){.wizard_content{padding:0}}.wizard-holder{width:100%;position:relative;display:flex}@media (max-width:50em){.wizard-holder{flex-direction:column}}.wizard-holder .connect-steps{flex-shrink:0;max-width:450px;padding:1rem}@media (max-width:50em){.wizard-holder .connect-steps{max-width:100%;flex-basis:auto;padding:.5rem}}.wizard-holder .wizard{flex-grow:1}.wizard_text{padding:0 0 25px;max-width:480px;font-size:14px}.wizard_more{user-select:none;display:inline-block;color:rgba(0,0,0,.5);font-size:12px;margin-top:20px}.wizard_more:hover{cursor:pointer;text-decoration:underline}.wizard_hello{font-size:18px;margin:15px 0 10px}.wizard_hello img{height:26px;vertical-align:sub;margin-right:3px}.wizard_button{min-width:137px;margin:0 .3rem 1rem}.wizard_buttons{margin:0 -.5rem;display:flex}@media (max-width:50em){.wizard_buttons{flex-direction:row;flex-wrap:wrap}}.wizard_network{padding:0 .5rem;margin-bottom:.35rem}.wizard_network .button{min-width:145px;text-align:center}.wizard_network .button i{margin-left:4px}.wizard_network .button-transparent{margin-bottom:10px}.wizard_network-icon{width:50px;height:50px;border-radius:100%;background-color:hsla(0,0%,7%,.05);margin:0 auto .8rem}.wizard_network-icon i{font-size:22px;line-height:50px}.wizard_list{padding:10px 0;display:flex;flex-wrap:wrap;margin:0 -.3125rem;max-width:49rem}.wizard_item{padding:5px;margin:5px;border:1px solid rgba(0,0,0,.05);display:flex;width:31%;align-items:center;vertical-align:middle;border-radius:4px;text-align:left}@media (max-width:50em){.wizard_item{width:100%;margin:0;margin-bottom:.625rem}}.wizard_item .description{font-size:12px;color:rgba(0,0,0,.75);margin-top:2px}.wizard_item .account-item_picture{float:none;margin-right:10px;flex-shrink:0}.wizard_info{max-width:20rem;text-align:left}.wizard_info .form-group{margin-bottom:1rem}.wizard_label{font-size:1rem;padding-top:.2rem;padding-bottom:.75rem}.wrpa-shortcode .wrpa-shortcode-form{display:inline-block;padding:4px 8px;border-radius:4px;background-color:rgba(0,0,0,.05);cursor:pointer;margin-right:4px}.wrpa-shortcode .wrpa-shortcode-form .wrpa-shortcode-form__shortcode{display:inline-block}.wrpa-shortcode .wrpa-shortcode-form .wrpa-shortcode-form__button{display:inline-block;opacity:.65;font-size:11px;font-style:italic;padding-right:3px}.connect_progress{position:absolute;left:calc(50% - 22px);top:30px}.connect_progress:after{clear:both;display:block;content:""}.connect_progress-point{display:block;float:left;margin-left:5px;width:8px;height:8px;border-radius:100%;background-color:rgba(26,83,230,.3)}.connect_progress-point__active{border:1px solid #1a53e6}.connect_progress-point__done{background-color:#1a53e6}.connect-actions{width:100%;max-width:42rem;border-top:2px solid rgba(0,0,0,.05);padding:1rem 0}.connect-actions .button{margin:0}@media (max-width:50em){.connect-actions{padding-bottom:2rem}}.connect-actions .fa-animated{font-size:2rem;color:rgba(26,83,230,.65);vertical-align:middle;margin-right:5px}@keyframes moveRightLeftLoop{0%{transform:translateX(-10px)}50%{transform:translateX(0)}to{transform:translateX(-10px)}}.moveRightLeftLoop{animation-iteration-count:infinite;animation-name:moveRightLeftLoop;animation-duration:1s}
|
1 |
+
.wrpa-expander{will-change:height;transform:translateZ(0);backface-visibility:hidden;perspective:1000px}.expand-enter-active,.expand-leave-active{transition:height .35s ease;overflow:hidden}.expand-enter,.expand-leave-to{height:0}.fade-enter,.fade-leave-to{opacity:0}.fade-enter-active,.fade-leave-active{transition:opacity .3s ease}.slide-up-enter{transform:translateY(10px);opacity:0}.slide-up-leave-to{transform:translateY(-10px);opacity:0}.slide-up-enter-active,.slide-up-leave-active{transition:all .3s ease}.slide-down-enter{transform:translateY(-10px);opacity:0}.slide-down-leave-to{transform:translateY(10px);opacity:0}.slide-down-enter-active,.slide-down-leave-active{transition:all .3s ease}.wpra-expander__title{cursor:pointer;user-select:none}.wpra-expander__title span{opacity:.5;vertical-align:bottom;transition:transform .3s ease}.wpra-expander__content{padding:0 .5rem;opacity:0;transition:opacity .3s ease}.wpra-expander--expanded .wpra-expander__content{opacity:1}.wpra-expander--expanded .wpra-expander__title span{transform:rotate(180deg)}[v-cloak] .vcloak--visible{display:block}[v-cloak] .vcloak--hidden{display:none}.vcloak--visible{min-height:60px;display:none}.loading-container{position:relative}.loading-container:before{display:block;content:"";position:absolute;left:calc(50% - 20px);top:calc(50% - 20px);box-sizing:border-box;height:40px;width:40px;border:0 solid #d0d0d0;border-radius:50%;box-shadow:inset 0 -12px 0 16px #d0d0d0;animation:rotate 1s infinite linear;z-index:3}.loading-container:after{display:block;content:"";position:absolute;z-index:2;background-color:hsla(0,0%,95%,.5);width:100%;height:100%;left:0;top:0}.loading-container--white:after{background-color:#fff}.loading-button{pointer-events:none;position:relative}.loading-button:before{display:block;content:"";position:absolute;left:calc(50% - 8px);top:calc(50% - 8px);box-sizing:border-box;height:16px;width:16px;border:0 solid #fff;border-radius:50%;box-shadow:inset 0 -4px 0 6px #fff;animation:rotate 1s infinite linear;z-index:3}.loading-button:after{display:block;content:"";position:absolute;z-index:2;background-color:inherit;width:100%;height:100%;left:0;top:0}.button-default.loading-button:before{box-shadow:inset 0 -4px 0 6px #6f6f6f}.loading-inline{display:inline-block;pointer-events:none;position:relative}.loading-inline:before{display:block;content:"";position:absolute;left:calc(50% + 1px);top:calc(50% - 11px);box-sizing:border-box;height:14px;width:14px;border:0 solid #d0d0d0;border-radius:50%;box-shadow:inset 0 -3px 0 5px #d0d0d0;animation:rotate 1s infinite linear;z-index:3}.loading-inline:after{display:block;content:"";position:absolute;z-index:2;background-color:inherit;width:100%;height:100%;left:0;top:0}@keyframes rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.wpra-wizard-head{display:flex;padding-bottom:1.5rem;padding-top:.75rem}.wpra-wizard-head__logo{flex-shrink:0}.wpra-wizard-head__logo img{width:57px}.wpra-wizard-head__copy{flex-grow:1;padding-left:1rem;display:flex;flex-direction:column;justify-content:center}.wpra-wizard-head__title{font-size:1.25rem;font-weight:500;padding-bottom:12px}.wpra-wizard-head__subtitle{font-size:1rem;opacity:.85}.wpra-cols{display:flex;margin:0 -.5rem;border-top:2px solid rgba(0,0,0,.05);padding-top:1.45rem}.wpra-cols-title{font-weight:400;font-size:1rem;padding-bottom:1rem}@media (max-width:50em){.wpra-cols{flex-wrap:wrap}}.wpra-cols .col{flex-basis:50%;padding:0 .5rem}@media (max-width:50em){.wpra-cols .col{flex-basis:100%;padding-bottom:1rem}}.wpra-cols .col img{max-width:100%}.wpra-cols .col p{font-size:14px;line-height:1.6}.wpra-cols .col p:first-child{margin-top:0}.wpra-feed-input{width:26rem;padding:6px 10px;max-width:100%}.wpra-feedback{display:flex}.wpra-feedback__photo{flex-shrink:0}.wpra-feedback__photo img{width:70px;border-radius:100%}.wpra-feedback__copy{padding-left:.5rem;flex-grow:1}.wpra-feedback__text{font-size:1rem;font-family:Georgia,serif;font-style:italic;line-height:1.5}.wpra-feedback__rating{padding:.25rem 0 .45rem}.wpra-feedback__rating span{color:#f8ca29}.wpra-feedback__by{opacity:.85}.wpra-feedback__by a{color:#617181}.wpra-demo-photo{margin-bottom:1rem;border-radius:4px;border:1px solid rgba(0,0,0,.15)}.wpra-feed-items{padding-left:.5rem;margin-bottom:1rem;border-left:4px solid #ff792b}.wpra-feed-items .wpra-feed-item{padding:.75rem}.wpra-feed-items .wpra-feed-item__link{padding-bottom:4px}.step-items{display:flex;position:relative;flex-direction:column;align-items:flex-end}.step-items .step-progress{position:absolute;width:3px;height:0;background-color:#00b479;left:17.5px;top:0;transition:height .3s ease;z-index:-1}.step-items .step-progress--1{height:50%}.step-items .step-progress--2{height:100%}@media (max-width:50em){.step-items .step-progress{display:none}}@media (max-width:50em){.step-items{padding:.625rem;flex-direction:row;align-items:flex-start}}.step-items .step-item{font-size:16px;width:15rem;margin-bottom:2.25rem;display:flex;background-color:#f1f1f1}.step-items .step-item:last-child{margin-bottom:0}@media (max-width:50em){.step-items .step-item{flex-direction:column;margin-bottom:0;align-items:center}}.step-items .step-item_active,.step-items .step-item_active .step-item__info,.step-items .step-item_active .step-item__status{opacity:1}@media (max-width:50em){.step-items .step-item_active{flex-grow:1}}.step-items .step-item__description{font-size:14px}.step-items .step-item__info{display:flex;align-items:center;padding-left:.75rem;opacity:.5}@media (max-width:50em){.step-items .step-item__info{padding-left:0;padding-top:.3rem;display:none}}.step-items .step-item__status{width:35px;height:35px;border-radius:50%;border:2px dashed rgba(0,0,0,.5);flex-shrink:0;opacity:.5;text-align:center;font-size:1.25rem;line-height:2.375rem;color:#00b479}.step-items .step-item__status span{display:block;margin:0!important;width:100%;line-height:35px;font-size:26px}.step-items .step-item_completed{opacity:1}.step-items .step-item_completed .step-item__status{border-style:solid;border-color:#00b479;opacity:1}.step-items .step-item_completed .step-item__status span{position:relative}.step-items .step-item_completed .step-item__info{opacity:.5}.wizard{width:100%;margin-left:1rem}@media (max-width:50em){.wizard{margin-left:0}}.wizard ol{margin-left:1.5rem;line-height:1.5;font-size:13px}.wizard ol ul{margin-bottom:1rem}.wizard .form-group{display:flex;align-items:center}@media (max-width:50em){.wizard .form-group{display:block;align-items:unset}.wizard .form-group input{margin-bottom:8px}}.wizard .form-group input{flex-shrink:0}.wizard .form-group .warning-icon{padding-left:4px;color:#ee5a65}.wizard .form-group a{flex-shrink:0;margin-left:6px}.wizard .button-clear{background-color:transparent;border:none;cursor:pointer;height:30px;line-height:28px;padding:0 12px 2px;vertical-align:baseline;opacity:.55}.wizard .button-clear:hover{opacity:.8}.wizard .button{vertical-align:baseline!important}.wizard .pad{display:flex}.wizard .pad-item--grow{flex-grow:1}.wizard .pad-item--no-shrink{flex-shrink:0}.wizard .wpra-success{padding-right:1rem;font-size:14px}.wizard_content{padding:1rem;font-size:14px;max-width:42rem;min-height:16rem;padding-top:12px}@media (max-width:50em){.wizard_content{padding:0}}.wizard-holder{width:100%;position:relative;display:flex}@media (max-width:50em){.wizard-holder{flex-direction:column}}.wizard-holder .connect-steps{flex-shrink:0;max-width:450px;padding:1rem}@media (max-width:50em){.wizard-holder .connect-steps{max-width:100%;flex-basis:auto;padding:.5rem}}.wizard-holder .wizard{flex-grow:1}.wizard_text{padding:0 0 25px;max-width:480px;font-size:14px}.wizard_more{user-select:none;display:inline-block;color:rgba(0,0,0,.5);font-size:12px;margin-top:20px}.wizard_more:hover{cursor:pointer;text-decoration:underline}.wizard_hello{font-size:18px;margin:15px 0 10px}.wizard_hello img{height:26px;vertical-align:sub;margin-right:3px}.wizard_button{min-width:137px;margin:0 .3rem 1rem}.wizard_buttons{margin:0 -.5rem;display:flex}@media (max-width:50em){.wizard_buttons{flex-direction:row;flex-wrap:wrap}}.wizard_network{padding:0 .5rem;margin-bottom:.35rem}.wizard_network .button{min-width:145px;text-align:center}.wizard_network .button i{margin-left:4px}.wizard_network .button-transparent{margin-bottom:10px}.wizard_network-icon{width:50px;height:50px;border-radius:100%;background-color:hsla(0,0%,7%,.05);margin:0 auto .8rem}.wizard_network-icon i{font-size:22px;line-height:50px}.wizard_list{padding:10px 0;display:flex;flex-wrap:wrap;margin:0 -.3125rem;max-width:49rem}.wizard_item{padding:5px;margin:5px;border:1px solid rgba(0,0,0,.05);display:flex;width:31%;align-items:center;vertical-align:middle;border-radius:4px;text-align:left}@media (max-width:50em){.wizard_item{width:100%;margin:0;margin-bottom:.625rem}}.wizard_item .description{font-size:12px;color:rgba(0,0,0,.75);margin-top:2px}.wizard_item .account-item_picture{float:none;margin-right:10px;flex-shrink:0}.wizard_info{max-width:20rem;text-align:left}.wizard_info .form-group{margin-bottom:1rem}.wizard_label{font-size:1rem;padding-top:.2rem;padding-bottom:.75rem}.wrpa-shortcode{display:flex}.wrpa-shortcode-form,.wrpa-shortcode-preview{padding-bottom:10px;padding-right:75px;flex-basis:50%}.wrpa-shortcode-form .wrpa-shortcode-label,.wrpa-shortcode-preview .wrpa-shortcode-label{font-size:1rem;padding-bottom:12px;line-height:1.5}.wrpa-shortcode-form .button.loading-button:before,.wrpa-shortcode-preview .button.loading-button:before{box-shadow:inset 0 -4px 0 6px #797979!important}.wrpa-shortcode .wrpa-shortcode-form{cursor:pointer}.wrpa-shortcode .wrpa-shortcode-form .wrpa-shortcode-form__shortcode{display:inline-block}.wrpa-shortcode .wrpa-shortcode-form .wrpa-shortcode-form__button{display:inline-block;opacity:.65;font-size:11px;font-style:italic;padding-right:3px}.connect_progress{position:absolute;left:calc(50% - 22px);top:30px}.connect_progress:after{clear:both;display:block;content:""}.connect_progress-point{display:block;float:left;margin-left:5px;width:8px;height:8px;border-radius:100%;background-color:rgba(26,83,230,.3)}.connect_progress-point__active{border:1px solid #1a53e6}.connect_progress-point__done{background-color:#1a53e6}.connect-actions{width:100%;max-width:42rem;border-top:2px solid rgba(0,0,0,.05);padding:1rem 0}.connect-actions .button{margin:0}@media (max-width:50em){.connect-actions{padding-bottom:2rem}}.connect-actions .fa-animated{font-size:2rem;color:rgba(26,83,230,.65);vertical-align:middle;margin-right:5px}@keyframes moveRightLeftLoop{0%{transform:translateX(-10px)}50%{transform:translateX(0)}to{transform:translateX(-10px)}}.moveRightLeftLoop{animation-iteration-count:infinite;animation-name:moveRightLeftLoop;animation-duration:1s}
|
css/plugins.min.css
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
[v-cloak] .vcloak--visible{display:block}[v-cloak] .vcloak--hidden{display:none}.vcloak--visible{min-height:60px;display:none}.loading-container{position:relative}.loading-container:before{display:block;content:"";position:absolute;left:calc(50% - 20px);top:calc(50% - 20px);box-sizing:border-box;height:40px;width:40px;border:0 solid #d0d0d0;border-radius:50%;box-shadow:inset 0 -12px 0 16px #d0d0d0;animation:rotate 1s infinite linear;z-index:3}.loading-container:after{display:block;content:"";position:absolute;z-index:2;background-color:hsla(0,0%,95%,.5);width:100%;height:100%;left:0;top:0}.loading-container--white:after{background-color:#fff}.loading-button{pointer-events:none;position:relative}.loading-button:before{display:block;content:"";position:absolute;left:calc(50% - 8px);top:calc(50% - 8px);box-sizing:border-box;height:16px;width:16px;border:0 solid #fff;border-radius:50%;box-shadow:inset 0 -4px 0 6px #fff;animation:rotate 1s infinite linear;z-index:3}.loading-button:after{display:block;content:"";position:absolute;z-index:2;background-color:inherit;width:100%;height:100%;left:0;top:0}.button-default.loading-button:before{box-shadow:inset 0 -4px 0 6px #6f6f6f}.loading-inline{display:inline-block;pointer-events:none;position:relative}.loading-inline:before{display:block;content:"";position:absolute;left:calc(50% + 1px);top:calc(50% - 11px);box-sizing:border-box;height:14px;width:14px;border:0 solid #d0d0d0;border-radius:50%;box-shadow:inset 0 -3px 0 5px #d0d0d0;animation:rotate 1s infinite linear;z-index:3}.loading-inline:after{display:block;content:"";position:absolute;z-index:2;background-color:inherit;width:100%;height:100%;left:0;top:0}@keyframes rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.modal{position:fixed;background-color:rgba(0,0,0,.65);width:100%;height:100%;left:0;top:0;z-index:9999;overflow-y:auto}.modal-opened{overflow:hidden}.modal__body{width:100%;max-width:30rem;margin:5rem auto;background-color:#fff;border-radius:4px}.modal__body--no-content-padding .modal__content{padding:0}.modal__body--wide{max-width:50rem}.modal__header{padding:.5rem 1rem;font-size:20px;font-weight:700;line-height:1.5;border-bottom:1px solid #eee}.modal__header.invisible-header{border:none;font-size:unset;font-weight:unset;padding-top:12px!important}.modal__header.invisible-header h3{margin-top:0;line-height:1.5;margin-bottom:0}.modal__header.invisible-header p{margin-top:.25rem;font-size:14px;opacity:.6;margin-bottom:0}.modal__header.invisible-header+.modal__content{padding-top:6px!important}.modal__header-buttons{font-weight:400}.modal__close{opacity:.5;cursor:pointer}.modal__close:hover{opacity:.8}.modal--right{float:right}.modal__content{padding:1rem}.modal__footer{padding:1rem;border-top:1px solid #eee;text-align:right}.modal__footer .button{display:inline-block!important;margin-left:4px!important}.modal__footer .footer-confirm{margin:0;padding:0;display:flex;align-items:center}.modal__footer .footer-confirm__buttons{flex-shrink:0}.modal__footer .footer-confirm__buttons--left{margin-right:auto;flex-grow:1;text-align:left}.modal__footer .footer-confirm__message{margin-right:auto}.modal__footer .footer-confirm__message.__right{flex-grow:1;padding-right:10px;text-align:right}.modal-transition-enter,.modal-transition-leave-to{opacity:0}.modal-transition-enter .modal__body,.modal-transition-leave-to .modal__body{opacity:0;transform:scaleX(.8) scaleY(.7)}.modal-transition-enter-active,.modal-transition-leave-active{transition:opacity .25s ease-out}.modal-transition-enter-active .modal__body,.modal-transition-leave-active .modal__body{transition:all .25s cubic-bezier(.665,1.65,0,.845)}.button-clear{border:none!important;background:transparent!important;box-shadow:none!important}.form-check{padding:4px 0}.form-check input{width:auto!important;margin:0 4px 0 0}.form-check input,.form-check label{display:inline-block!important}.form-group{padding-bottom:8px}.form-group label{display:block}.form-group>label{margin-bottom:2px}.form-group input,.form-group textarea{display:block;width:100%}.form-group:last-child{padding-bottom:0}.form-group p:first-child{margin-top:0}.form-group p:last-child{margin-bottom:0}.form-group .error{margin:0!important}.wpra-plugin-disable-poll__logo img{max-height:40px}
|
css/src/intro/steps.scss
CHANGED
@@ -545,13 +545,24 @@ $primary-color: #1a53e6;
|
|
545 |
}
|
546 |
|
547 |
.wrpa-shortcode {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
548 |
.wrpa-shortcode-form {
|
549 |
-
display: inline-block;
|
550 |
-
padding: 4px 8px;
|
551 |
-
border-radius: 4px;
|
552 |
-
background-color: $deep-gray;
|
553 |
cursor: pointer;
|
554 |
-
margin-right: 4px;
|
555 |
.wrpa-shortcode-form__shortcode {
|
556 |
display: inline-block;
|
557 |
}
|
545 |
}
|
546 |
|
547 |
.wrpa-shortcode {
|
548 |
+
display: flex;
|
549 |
+
&-form, &-preview {
|
550 |
+
padding-bottom: 10px;
|
551 |
+
padding-right: 75px;
|
552 |
+
flex-basis: 50%;
|
553 |
+
.wrpa-shortcode-label {
|
554 |
+
font-size: 1rem;
|
555 |
+
padding-bottom: 12px;
|
556 |
+
line-height: 1.5;
|
557 |
+
}
|
558 |
+
.button.loading-button {
|
559 |
+
&::before {
|
560 |
+
box-shadow: inset 0 -4px 0 6px #797979 !important;
|
561 |
+
}
|
562 |
+
}
|
563 |
+
}
|
564 |
.wrpa-shortcode-form {
|
|
|
|
|
|
|
|
|
565 |
cursor: pointer;
|
|
|
566 |
.wrpa-shortcode-form__shortcode {
|
567 |
display: inline-block;
|
568 |
}
|
css/src/plugins/form.scss
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.form {
|
2 |
+
&-check {
|
3 |
+
input {
|
4 |
+
display: inline-block !important;
|
5 |
+
width: auto !important;
|
6 |
+
margin: 0 4px 0 0;
|
7 |
+
}
|
8 |
+
label {
|
9 |
+
display: inline-block !important;
|
10 |
+
}
|
11 |
+
padding: 4px 0;
|
12 |
+
}
|
13 |
+
&-group {
|
14 |
+
padding-bottom: 8px;
|
15 |
+
label {
|
16 |
+
display: block;
|
17 |
+
}
|
18 |
+
& > label {
|
19 |
+
margin-bottom: 2px;
|
20 |
+
}
|
21 |
+
input, textarea {
|
22 |
+
display: block;
|
23 |
+
width: 100%;
|
24 |
+
}
|
25 |
+
&:last-child {
|
26 |
+
padding-bottom: 0;
|
27 |
+
}
|
28 |
+
p {
|
29 |
+
&:first-child {
|
30 |
+
margin-top: 0;
|
31 |
+
}
|
32 |
+
&:last-child {
|
33 |
+
margin-bottom: 0;
|
34 |
+
}
|
35 |
+
}
|
36 |
+
.error {
|
37 |
+
margin: 0 !important;
|
38 |
+
}
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
.wpra-plugin-disable-poll {
|
43 |
+
&__logo {
|
44 |
+
img {
|
45 |
+
max-height: 40px;
|
46 |
+
}
|
47 |
+
}
|
48 |
+
}
|
css/src/plugins/index.scss
ADDED
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
$white: #fff;
|
2 |
+
$radius: 4px;
|
3 |
+
|
4 |
+
@mixin breakpoint($point) {
|
5 |
+
@if $point == desktop {
|
6 |
+
@media (min-width: 70em) { @content ; }
|
7 |
+
}
|
8 |
+
@else if $point == laptop {
|
9 |
+
@media (min-width: 64em) { @content ; }
|
10 |
+
}
|
11 |
+
@else if $point == tablet {
|
12 |
+
@media (max-width: 50em) { @content ; }
|
13 |
+
}
|
14 |
+
@else if $point == phablet {
|
15 |
+
@media (min-width: 37.5em) { @content ; }
|
16 |
+
}
|
17 |
+
@else if $point == mobileonly {
|
18 |
+
@media (max-width: 37.5em) { @content ; }
|
19 |
+
|
20 |
+
}
|
21 |
+
}
|
22 |
+
|
23 |
+
@import "./../intro/loading";
|
24 |
+
@import "modal";
|
25 |
+
@import "form";
|
css/src/plugins/modal.scss
ADDED
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.modal {
|
2 |
+
&-opened {
|
3 |
+
overflow: hidden;
|
4 |
+
}
|
5 |
+
|
6 |
+
position: fixed;
|
7 |
+
background-color: rgba(0, 0, 0, 0.65);
|
8 |
+
width: 100%;
|
9 |
+
height: 100%;
|
10 |
+
left: 0;
|
11 |
+
top: 0;
|
12 |
+
z-index: 9999;
|
13 |
+
overflow-y: auto;
|
14 |
+
|
15 |
+
@include breakpoint(mobile) {
|
16 |
+
z-index: 100000;
|
17 |
+
}
|
18 |
+
|
19 |
+
&__body {
|
20 |
+
width: 100%;
|
21 |
+
max-width: 30rem;
|
22 |
+
margin: 5rem auto;
|
23 |
+
|
24 |
+
background-color: $white;
|
25 |
+
border-radius: $radius;
|
26 |
+
|
27 |
+
&--no-content-padding {
|
28 |
+
.modal__content {
|
29 |
+
padding: 0;
|
30 |
+
}
|
31 |
+
}
|
32 |
+
|
33 |
+
&--wide {
|
34 |
+
max-width: 50rem;
|
35 |
+
}
|
36 |
+
|
37 |
+
@include breakpoint(mobile) {
|
38 |
+
min-height: 100vh;
|
39 |
+
margin: 0;
|
40 |
+
border-radius: 0;
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
&__header {
|
45 |
+
padding: .5rem 1rem;
|
46 |
+
font-size: 20px;
|
47 |
+
font-weight: bold;
|
48 |
+
line-height: 1.5;
|
49 |
+
border-bottom: 1px solid #eee;
|
50 |
+
|
51 |
+
&.invisible-header {
|
52 |
+
border: none;
|
53 |
+
font-size: unset;
|
54 |
+
font-weight: unset;
|
55 |
+
padding-top: 12px !important;
|
56 |
+
h3 {
|
57 |
+
margin-top: 0;
|
58 |
+
line-height: 1.5;
|
59 |
+
margin-bottom: 0;
|
60 |
+
}
|
61 |
+
p {
|
62 |
+
margin-top: .25rem;
|
63 |
+
font-size: 14px;
|
64 |
+
opacity: .6;
|
65 |
+
margin-bottom: 0;
|
66 |
+
}
|
67 |
+
& + .modal__content {
|
68 |
+
padding-top: 6px !important;
|
69 |
+
}
|
70 |
+
}
|
71 |
+
|
72 |
+
@include breakpoint(mobile) {
|
73 |
+
position: relative;
|
74 |
+
|
75 |
+
.modal--right {
|
76 |
+
position: absolute;
|
77 |
+
top: 0;
|
78 |
+
padding: 6px 1rem 0 1rem;
|
79 |
+
right: 0;
|
80 |
+
background-color: white;
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
&-buttons {
|
85 |
+
font-weight: normal;
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
&__close {
|
90 |
+
opacity: .5;
|
91 |
+
cursor: pointer;
|
92 |
+
&:hover {
|
93 |
+
opacity: .8;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
&--right {
|
98 |
+
float: right;
|
99 |
+
}
|
100 |
+
|
101 |
+
&__content {
|
102 |
+
padding: 1rem;
|
103 |
+
}
|
104 |
+
|
105 |
+
&__footer {
|
106 |
+
padding: 1rem;
|
107 |
+
border-top: 1px solid #eee;
|
108 |
+
text-align: right;
|
109 |
+
|
110 |
+
.button {
|
111 |
+
display: inline-block !important;
|
112 |
+
margin-left: 4px !important;
|
113 |
+
}
|
114 |
+
.footer-confirm {
|
115 |
+
margin: 0;
|
116 |
+
padding: 0;
|
117 |
+
display: flex;
|
118 |
+
align-items: center;
|
119 |
+
|
120 |
+
@include breakpoint(mobile) {
|
121 |
+
display: block;
|
122 |
+
&__message {
|
123 |
+
padding-right: 0;
|
124 |
+
padding-bottom: 10px;
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
&__buttons {
|
129 |
+
flex-shrink: 0;
|
130 |
+
|
131 |
+
&--left {
|
132 |
+
margin-right: auto;
|
133 |
+
flex-grow: 1;
|
134 |
+
text-align: left;
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
&__message {
|
139 |
+
margin-right: auto;
|
140 |
+
&.__right {
|
141 |
+
flex-grow: 1;
|
142 |
+
padding-right: 10px;
|
143 |
+
text-align: right;
|
144 |
+
}
|
145 |
+
}
|
146 |
+
}
|
147 |
+
}
|
148 |
+
}
|
149 |
+
|
150 |
+
.modal-transition {
|
151 |
+
&-enter, &-leave-to {
|
152 |
+
opacity: 0;
|
153 |
+
|
154 |
+
.modal__body {
|
155 |
+
opacity: 0;
|
156 |
+
transform: scaleX(.8) scaleY(.7);
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
&-enter-active, &-leave-active {
|
161 |
+
transition: opacity 0.25s ease-out;
|
162 |
+
|
163 |
+
.modal__body {
|
164 |
+
transition: all .25s cubic-bezier(.665,1.65,0,.845);
|
165 |
+
}
|
166 |
+
}
|
167 |
+
}
|
168 |
+
|
169 |
+
.button-clear {
|
170 |
+
border: none !important;
|
171 |
+
background: transparent !important;
|
172 |
+
box-shadow: none !important;
|
173 |
+
}
|
css/src/update/index.scss
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
|
3 |
+
.wrap--wpra-update {
|
4 |
+
padding-top: 1rem;
|
5 |
+
width: 100%;
|
6 |
+
max-width: 880px;
|
7 |
+
margin: 0 auto;
|
8 |
+
}
|
9 |
+
|
10 |
+
.wpra-text-center {
|
11 |
+
text-align: center;
|
12 |
+
}
|
13 |
+
|
14 |
+
.wpra-updates {
|
15 |
+
list-style: unset;
|
16 |
+
padding: 0 1.25rem;
|
17 |
+
}
|
18 |
+
|
19 |
+
.wpra-inline-form {
|
20 |
+
display: flex;
|
21 |
+
align-items: baseline;
|
22 |
+
|
23 |
+
button {
|
24 |
+
margin-right: 12px !important;
|
25 |
+
}
|
26 |
+
|
27 |
+
small {
|
28 |
+
font-size: 12px;
|
29 |
+
opacity: .75;
|
30 |
+
}
|
31 |
+
}
|
32 |
+
|
33 |
+
|
34 |
+
.wpra-update-head__title {
|
35 |
+
font-size: 24px;
|
36 |
+
font-weight: 500;
|
37 |
+
padding: 1.5rem 0 1.5rem;
|
38 |
+
}
|
39 |
+
|
40 |
+
.wpra-update__logo img {
|
41 |
+
width: 56px;
|
42 |
+
}
|
43 |
+
|
44 |
+
.button-icon span {
|
45 |
+
vertical-align: baseline;
|
46 |
+
margin-right: -7px;
|
47 |
+
opacity: .6;
|
48 |
+
font-size: 16px;
|
49 |
+
top: 4px;
|
50 |
+
position: relative;
|
51 |
+
}
|
52 |
+
|
53 |
+
.wpra-links {
|
54 |
+
padding-top: .5rem;
|
55 |
+
}
|
56 |
+
|
57 |
+
.wpra-update-head__link {
|
58 |
+
font-size: 1rem;
|
59 |
+
padding-bottom: 1.5rem;
|
60 |
+
}
|
61 |
+
|
62 |
+
.wpra-update-feature {
|
63 |
+
display: flex;
|
64 |
+
}
|
65 |
+
|
66 |
+
.wpra-update-feature__text h3 {
|
67 |
+
margin-top: 8px;
|
68 |
+
}
|
69 |
+
|
70 |
+
.wpra-update-feature__image {
|
71 |
+
width: 55rem;
|
72 |
+
overflow: hidden;
|
73 |
+
position: relative;
|
74 |
+
margin: -11px -12px -23px 0;
|
75 |
+
|
76 |
+
img {
|
77 |
+
max-height: 29rem;
|
78 |
+
position: absolute;
|
79 |
+
bottom: 12px;
|
80 |
+
right: 12px;
|
81 |
+
filter: drop-shadow(0px 2px 3px rgba(0,0,0,.125));
|
82 |
+
}
|
83 |
+
}
|
css/update.min.css
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
.wrap--wpra-update{padding-top:1rem;width:100%;max-width:880px;margin:0 auto}.wpra-text-center{text-align:center}.wpra-updates{list-style:unset;padding:0 1.25rem}.wpra-inline-form{display:flex;align-items:baseline}.wpra-inline-form button{margin-right:12px!important}.wpra-inline-form small{font-size:12px;opacity:.75}.wpra-update-head__title{font-size:24px;font-weight:500;padding:1.5rem 0}.wpra-update__logo img{width:56px}.button-icon span{vertical-align:baseline;margin-right:-7px;opacity:.6;font-size:16px;top:4px;position:relative}.wpra-links{padding-top:.5rem}.wpra-update-head__link{font-size:1rem;padding-bottom:1.5rem}.wpra-update-feature{display:flex}.wpra-update-feature__text h3{margin-top:8px}.wpra-update-feature__image{width:55rem;overflow:hidden;position:relative;margin:-11px -12px -23px 0}.wpra-update-feature__image img{max-height:29rem;position:absolute;bottom:12px;right:12px;filter:drop-shadow(0 2px 3px rgba(0,0,0,.125))}
|
images/light-line-logo.png
ADDED
Binary file
|
images/wp-rss-aggregator-support-beacon.png
ADDED
Binary file
|
includes/Aventura/Wprss/Core/Licensing/Manager.php
CHANGED
@@ -439,7 +439,7 @@ class Manager {
|
|
439 |
$data = $this->sendApiRequest( $addonId, $action, $return );
|
440 |
$status = is_object( $data ) ? $data->license : $data;
|
441 |
|
442 |
-
return ( in_array($status,
|
443 |
? $this->sendApiRequest( $addonId . static::LIFETIME_ADDON_ID_SUFFIX, $action, $return )
|
444 |
: $data;
|
445 |
}
|
439 |
$data = $this->sendApiRequest( $addonId, $action, $return );
|
440 |
$status = is_object( $data ) ? $data->license : $data;
|
441 |
|
442 |
+
return ( in_array($status, array('invalid', 'item_name_mismatch', 'failed')) )
|
443 |
? $this->sendApiRequest( $addonId . static::LIFETIME_ADDON_ID_SUFFIX, $action, $return )
|
444 |
: $data;
|
445 |
}
|
includes/Aventura/Wprss/Core/Model/BulkSourceImport/ArrayImporter.php
CHANGED
@@ -38,16 +38,16 @@ class ArrayImporter extends AbstractWpImporter implements ImporterInterface
|
|
38 |
protected function _inputToSourcesList($input)
|
39 |
{
|
40 |
if (!is_array($input)) {
|
41 |
-
return
|
42 |
}
|
43 |
|
44 |
-
$sources =
|
45 |
foreach ($input as $k => $v) {
|
46 |
-
$sources[] =
|
47 |
ImporterInterface::SK_URL => $k,
|
48 |
ImporterInterface::SK_TITLE => $v,
|
49 |
-
'status' => 'publish'
|
50 |
-
|
51 |
}
|
52 |
|
53 |
return $sources;
|
38 |
protected function _inputToSourcesList($input)
|
39 |
{
|
40 |
if (!is_array($input)) {
|
41 |
+
return array();
|
42 |
}
|
43 |
|
44 |
+
$sources = array();
|
45 |
foreach ($input as $k => $v) {
|
46 |
+
$sources[] = array(
|
47 |
ImporterInterface::SK_URL => $k,
|
48 |
ImporterInterface::SK_TITLE => $v,
|
49 |
+
'status' => 'publish',
|
50 |
+
);
|
51 |
}
|
52 |
|
53 |
return $sources;
|
includes/Aventura/Wprss/Core/Model/Regex/AbstractRegex.php
CHANGED
@@ -35,9 +35,10 @@ class AbstractRegex extends Core\Model\ModelAbstract
|
|
35 |
}
|
36 |
|
37 |
$string = (array)$string;
|
38 |
-
|
|
|
39 |
if (is_array($string)) {
|
40 |
-
return $
|
41 |
}
|
42 |
return preg_quote($string, $delimiter);
|
43 |
}, $string);
|
@@ -108,4 +109,4 @@ class AbstractRegex extends Core\Model\ModelAbstract
|
|
108 |
{
|
109 |
return preg_match($pattern, $subject, $matches, $flags, $offset);
|
110 |
}
|
111 |
-
}
|
35 |
}
|
36 |
|
37 |
$string = (array)$string;
|
38 |
+
$self = $this;
|
39 |
+
return array_map(function ($string) use ($delimiter, $self) {
|
40 |
if (is_array($string)) {
|
41 |
+
return $self->quoteAll($string, $delimiter);
|
42 |
}
|
43 |
return preg_quote($string, $delimiter);
|
44 |
}, $string);
|
109 |
{
|
110 |
return preg_match($pattern, $subject, $matches, $flags, $offset);
|
111 |
}
|
112 |
+
}
|
includes/admin-activate.php
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if (wprss_can_use_twig()) {
|
4 |
+
/* The introduction page module */
|
5 |
+
require_once(WPRSS_INC . 'admin-intro-page.php');
|
6 |
+
/* The update page module */
|
7 |
+
require_once(WPRSS_INC . 'admin-update-page.php');
|
8 |
+
}
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Detects an activation and redirects the user to the correct page (intro or update).
|
12 |
+
*
|
13 |
+
* @since 4.12.1
|
14 |
+
*/
|
15 |
+
add_action('admin_init', function () {
|
16 |
+
// Continue only if during an activation redirect
|
17 |
+
if (!get_transient('_wprss_activation_redirect')) {
|
18 |
+
return;
|
19 |
+
}
|
20 |
+
|
21 |
+
// Delete the redirect transient
|
22 |
+
delete_transient('_wprss_activation_redirect');
|
23 |
+
|
24 |
+
// Continue only if activating from a non-network site and not bulk activating plugins
|
25 |
+
if (is_network_admin() || isset($_GET['activate-multi'])) {
|
26 |
+
return;
|
27 |
+
}
|
28 |
+
|
29 |
+
if (wprss_should_do_intro_page()) {
|
30 |
+
wp_safe_redirect(wprss_get_intro_page_url());
|
31 |
+
return;
|
32 |
+
}
|
33 |
+
|
34 |
+
if (wprss_should_do_update_page()) {
|
35 |
+
wp_safe_redirect(wprss_get_update_page_url());
|
36 |
+
return;
|
37 |
+
}
|
38 |
+
});
|
includes/admin-addons.php
CHANGED
@@ -12,8 +12,6 @@
|
|
12 |
|
13 |
?>
|
14 |
<div class="wrap">
|
15 |
-
<?php screen_icon( 'wprss-aggregator' ); ?>
|
16 |
-
|
17 |
<h2><?php _e( 'More Features With Our Premium Add-Ons', WPRSS_TEXT_DOMAIN ); ?></h2>
|
18 |
<p><?php echo sprintf(__( 'The following <a href="%1$s" target="_blank">add-ons</a> are available to increase the functionality of the WP RSS Aggregator plugin.', WPRSS_TEXT_DOMAIN ), 'https://www.wprssaggregator.com/extensions') ?></p>
|
19 |
<p><?php echo sprintf(__(
|
12 |
|
13 |
?>
|
14 |
<div class="wrap">
|
|
|
|
|
15 |
<h2><?php _e( 'More Features With Our Premium Add-Ons', WPRSS_TEXT_DOMAIN ); ?></h2>
|
16 |
<p><?php echo sprintf(__( 'The following <a href="%1$s" target="_blank">add-ons</a> are available to increase the functionality of the WP RSS Aggregator plugin.', WPRSS_TEXT_DOMAIN ), 'https://www.wprssaggregator.com/extensions') ?></p>
|
17 |
<p><?php echo sprintf(__(
|
includes/admin-ajax-notice.php
CHANGED
@@ -1267,7 +1267,9 @@ function wprss_is_wprss_page() {
|
|
1267 |
'wprss-debugging',
|
1268 |
'wprss-addons',
|
1269 |
'wprss-welcome',
|
1270 |
-
'wprss-help'
|
|
|
|
|
1271 |
));
|
1272 |
|
1273 |
$is_wprss_post = in_array($postType, $wprss_post_types, true);
|
1267 |
'wprss-debugging',
|
1268 |
'wprss-addons',
|
1269 |
'wprss-welcome',
|
1270 |
+
'wprss-help',
|
1271 |
+
'wpra-intro',
|
1272 |
+
'wpra-update',
|
1273 |
));
|
1274 |
|
1275 |
$is_wprss_post = in_array($postType, $wprss_post_types, true);
|
includes/admin-debugging.php
CHANGED
@@ -246,8 +246,6 @@ use Aventura\Wprss\Core\Model\AdminAjaxNotice\NoticeInterface;
|
|
246 |
?>
|
247 |
|
248 |
<div class="wrap">
|
249 |
-
<?php screen_icon( 'wprss-aggregator' ); ?>
|
250 |
-
|
251 |
<h2><?php _e( 'Debugging', WPRSS_TEXT_DOMAIN ); ?></h2>
|
252 |
<?php
|
253 |
if ( isset( $_GET['debug_message'] )) {//&& ( check_admin_referer( 'wprss-delete-import-feed-items' ) || check_admin_referer( 'wprss-update-feed-items' ) ) ) {
|
@@ -375,7 +373,9 @@ use Aventura\Wprss\Core\Model\AdminAjaxNotice\NoticeInterface;
|
|
375 |
'wprss_settings_notices',
|
376 |
'wprss_addon_notices',
|
377 |
'wprss_pwsv',
|
378 |
-
'wprss_db_version'
|
|
|
|
|
379 |
)
|
380 |
);
|
381 |
// Delete the settings
|
246 |
?>
|
247 |
|
248 |
<div class="wrap">
|
|
|
|
|
249 |
<h2><?php _e( 'Debugging', WPRSS_TEXT_DOMAIN ); ?></h2>
|
250 |
<?php
|
251 |
if ( isset( $_GET['debug_message'] )) {//&& ( check_admin_referer( 'wprss-delete-import-feed-items' ) || check_admin_referer( 'wprss-update-feed-items' ) ) ) {
|
373 |
'wprss_settings_notices',
|
374 |
'wprss_addon_notices',
|
375 |
'wprss_pwsv',
|
376 |
+
'wprss_db_version',
|
377 |
+
WPRSS_INTRO_DID_INTRO_OPTION,
|
378 |
+
WPRSS_UPDATE_PAGE_PREV_VERSION_OPTION
|
379 |
)
|
380 |
);
|
381 |
// Delete the settings
|
includes/admin-help.php
CHANGED
@@ -2,6 +2,17 @@
|
|
2 |
|
3 |
use Aventura\Wprss\Core\Licensing\License\Status as License_Status;
|
4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
/**
|
6 |
* Build the Help page
|
7 |
*
|
@@ -11,8 +22,6 @@
|
|
11 |
?>
|
12 |
|
13 |
<div class="wrap">
|
14 |
-
<?php screen_icon( 'wprss-aggregator' ); ?>
|
15 |
-
|
16 |
<h2><?php _e( 'Help & Support', WPRSS_TEXT_DOMAIN ); ?></h2>
|
17 |
<h3><?php _e( 'Documentation', WPRSS_TEXT_DOMAIN ) ?></h3>
|
18 |
<?php
|
@@ -46,10 +55,47 @@
|
|
46 |
wprss_free_help_display();
|
47 |
}
|
48 |
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
</div>
|
50 |
<?php
|
51 |
}
|
52 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
|
54 |
/**
|
55 |
* Print the premium help section, linking to the contact us page on the site.
|
2 |
|
3 |
use Aventura\Wprss\Core\Licensing\License\Status as License_Status;
|
4 |
|
5 |
+
/**
|
6 |
+
* Checks if the HS becaon is enabled or not.
|
7 |
+
*
|
8 |
+
* @since 4.12.1
|
9 |
+
*
|
10 |
+
* @return bool True if enabled, false if not.
|
11 |
+
*/
|
12 |
+
function wprss_is_help_beacon_enabled() {
|
13 |
+
return (int) get_option('wprss_hs_beacon_enabled', 0) === 1;
|
14 |
+
}
|
15 |
+
|
16 |
/**
|
17 |
* Build the Help page
|
18 |
*
|
22 |
?>
|
23 |
|
24 |
<div class="wrap">
|
|
|
|
|
25 |
<h2><?php _e( 'Help & Support', WPRSS_TEXT_DOMAIN ); ?></h2>
|
26 |
<h3><?php _e( 'Documentation', WPRSS_TEXT_DOMAIN ) ?></h3>
|
27 |
<?php
|
55 |
wprss_free_help_display();
|
56 |
}
|
57 |
?>
|
58 |
+
<h3><?php _e( 'Built-in Help Beacon', WPRSS_TEXT_DOMAIN ) ?></h3>
|
59 |
+
<form method="POST">
|
60 |
+
<p>
|
61 |
+
<?php _e('The help beacon is an interactive button that appears on the bottom-right section of WP RSS Aggregator admin pages.', WPRSS_TEXT_DOMAIN); ?>
|
62 |
+
<?php _e('It provides access to our documentation and (if you have a valid license for any of our add-ons) you can also contact our support team directly.', WPRSS_TEXT_DOMAIN); ?>
|
63 |
+
</p>
|
64 |
+
<p>
|
65 |
+
<?php _e('The beacon tracks what pages you were on before clicking it. This helps it provide relevant help results and also helps the support team better understand the problem you are facing.', WPRSS_TEXT_DOMAIN); ?>
|
66 |
+
<?php _e('The beacon only works on WP RSS Aggregator admin pages and does not track your mouse clicks and keyboard input.', WPRSS_TEXT_DOMAIN); ?>
|
67 |
+
</p>
|
68 |
+
<?php if (wprss_is_help_beacon_enabled()): ?>
|
69 |
+
<p><?php _e('The support beacon is currently <b>enabled</b>.', WPRSS_TEXT_DOMAIN); ?></p>
|
70 |
+
<button type="submit" name="wprss_hs_beacon_enabled" value="0" class="button button-secondary">
|
71 |
+
<?php _e('Disable support beacon', WPRSS_TEXT_DOMAIN); ?>
|
72 |
+
</button>
|
73 |
+
<?php else: ?>
|
74 |
+
<p><?php _e('By enabling the help beacon, you are consenting to this data collection.', WPRSS_TEXT_DOMAIN); ?></p>
|
75 |
+
<button type="submit" name="wprss_hs_beacon_enabled" value="1" class="button button-primary">
|
76 |
+
<?php _e('Enable support beacon', WPRSS_TEXT_DOMAIN); ?>
|
77 |
+
</button>
|
78 |
+
<?php endif; ?>
|
79 |
+
|
80 |
+
<?php wp_nonce_field('wprss_hs_beacon_enabled'); ?>
|
81 |
+
</form>
|
82 |
</div>
|
83 |
<?php
|
84 |
}
|
85 |
|
86 |
+
// Handler to update the HS beacon enabled option
|
87 |
+
add_action('init', function () {
|
88 |
+
if (!is_admin()) {
|
89 |
+
return;
|
90 |
+
}
|
91 |
+
|
92 |
+
$enabled = filter_input(INPUT_POST, 'wprss_hs_beacon_enabled', FILTER_VALIDATE_INT);
|
93 |
+
|
94 |
+
if ($enabled !== null) {
|
95 |
+
check_admin_referer('wprss_hs_beacon_enabled');
|
96 |
+
update_option('wprss_hs_beacon_enabled', $enabled);
|
97 |
+
}
|
98 |
+
});
|
99 |
|
100 |
/**
|
101 |
* Print the premium help section, linking to the contact us page on the site.
|
includes/admin-import-export.php
CHANGED
@@ -160,8 +160,6 @@ use Aventura\Wprss\Core\Model\BulkSourceImport\ServiceProvider;
|
|
160 |
function wprss_import_export_settings_page_display() {
|
161 |
if ( !isset( $_POST['export'] ) ) { ?>
|
162 |
<div class="wrap">
|
163 |
-
<?php screen_icon( 'wprss-aggregator' ); ?>
|
164 |
-
|
165 |
<!-- Bulk Add -->
|
166 |
<h2><?php _e( 'Bulk Feed Import', WPRSS_TEXT_DOMAIN ); ?></h2>
|
167 |
<p><?php _e( 'Import multiple feed sources at once, by entering the name and URLs of your feeds below.', WPRSS_TEXT_DOMAIN ); ?></p>
|
@@ -221,4 +219,4 @@ add_filter(\WPRSS_EVENT_PREFIX .'core_container_init', function(WritableContaine
|
|
221 |
'event_prefix' => \WPRSS_EVENT_PREFIX,
|
222 |
));
|
223 |
$container->register($serviceProvider);
|
224 |
-
});
|
160 |
function wprss_import_export_settings_page_display() {
|
161 |
if ( !isset( $_POST['export'] ) ) { ?>
|
162 |
<div class="wrap">
|
|
|
|
|
163 |
<!-- Bulk Add -->
|
164 |
<h2><?php _e( 'Bulk Feed Import', WPRSS_TEXT_DOMAIN ); ?></h2>
|
165 |
<p><?php _e( 'Import multiple feed sources at once, by entering the name and URLs of your feeds below.', WPRSS_TEXT_DOMAIN ); ?></p>
|
219 |
'event_prefix' => \WPRSS_EVENT_PREFIX,
|
220 |
));
|
221 |
$container->register($serviceProvider);
|
222 |
+
});
|
includes/{admin-intro.php → admin-intro-page.php}
RENAMED
@@ -17,30 +17,6 @@ define('WPRSS_INTRO_FEED_URL_PARAM', 'wprss_intro_feed_url');
|
|
17 |
define('WPRSS_INTRO_SHORTCODE_PAGE_OPTION', 'wprss_intro_shortcode_page');
|
18 |
define('WPRSS_INTRO_SHORTCODE_PAGE_PREVIEW_PARAM', 'wprss_preview_shortcode_page');
|
19 |
|
20 |
-
/**
|
21 |
-
* Detects an activation and redirects the user to the intro page.
|
22 |
-
*
|
23 |
-
* @since [*next-version*]
|
24 |
-
*/
|
25 |
-
add_action('admin_init', function () {
|
26 |
-
// Continue only if during an activation redirect
|
27 |
-
if (!get_transient('_wprss_activation_redirect')) {
|
28 |
-
return;
|
29 |
-
}
|
30 |
-
|
31 |
-
// Delete the redirect transient
|
32 |
-
delete_transient('_wprss_activation_redirect');
|
33 |
-
|
34 |
-
// Continue only if activating from a non-network site and not bulk activating plugins
|
35 |
-
if (is_network_admin() || isset($_GET['activate-multi'])) {
|
36 |
-
return;
|
37 |
-
}
|
38 |
-
|
39 |
-
if (wprss_should_do_intro()) {
|
40 |
-
wp_safe_redirect(wprss_get_intro_page_url());
|
41 |
-
}
|
42 |
-
});
|
43 |
-
|
44 |
/**
|
45 |
* Registers the introduction page.
|
46 |
*
|
@@ -51,9 +27,9 @@ add_action('admin_menu', function () {
|
|
51 |
null,
|
52 |
__('Welcome to WP RSS Aggregator'),
|
53 |
__('Welcome to WP RSS Aggregator'),
|
54 |
-
'
|
55 |
WPRSS_INTRO_PAGE_SLUG,
|
56 |
-
'
|
57 |
);
|
58 |
});
|
59 |
|
@@ -66,13 +42,15 @@ add_action('admin_menu', function () {
|
|
66 |
* @throws Twig_Error_Runtime
|
67 |
* @throws Twig_Error_Syntax
|
68 |
*/
|
69 |
-
function
|
70 |
{
|
71 |
-
|
|
|
|
|
72 |
wp_enqueue_style('intro-wizard', WPRSS_CSS . 'intro.min.css');
|
73 |
|
74 |
$nonce = wp_create_nonce(WPRSS_INTRO_NONCE_NAME);
|
75 |
-
wp_localize_script('intro-wizard', 'wprssWizardConfig',
|
76 |
'previewUrl' => admin_url('admin.php?wprss_preview_shortcode_page=1&nonce=' . $nonce),
|
77 |
'feedListUrl' => admin_url('edit.php?post_type=wprss_feed'),
|
78 |
'addOnsUrl' => 'https://www.wprssaggregator.com/plugins/?utm_source=core_plugin&utm_medium=onboarding_wizard&utm_campaign=onboarding_wizard_addons_button&utm_content=addons_button',
|
@@ -80,19 +58,19 @@ function wpra_render_intro_page()
|
|
80 |
'demoImageUrl' => WPRSS_IMG . 'welcome-page/demo.png',
|
81 |
'feedbackUrl' => 'https://wordpress.org/support/topic/does-everything-i-need-16/',
|
82 |
'knowledgeBaseUrl' => 'https://kb.wprssaggregator.com/',
|
83 |
-
'feedEndpoint' =>
|
84 |
'url' => admin_url('admin-ajax.php'),
|
85 |
-
'defaultPayload' =>
|
86 |
'action' => 'wprss_create_intro_feed',
|
87 |
'nonce' => $nonce,
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
|
92 |
-
echo wprss_render_template('admin-intro-page.twig',
|
93 |
'title' => 'Welcome to WP RSS Aggregator 👋',
|
94 |
'subtitle' => 'Follow these introductory steps to get started with WP RSS Aggregator.',
|
95 |
-
|
96 |
}
|
97 |
|
98 |
/**
|
@@ -103,9 +81,9 @@ function wpra_render_intro_page()
|
|
103 |
add_action('wp_ajax_wprss_set_intro_step', function () {
|
104 |
check_ajax_referer(WPRSS_INTRO_NONCE_NAME, 'nonce');
|
105 |
if (!current_user_can('manage_options')) {
|
106 |
-
wp_die('', '',
|
107 |
'response' => 403,
|
108 |
-
|
109 |
}
|
110 |
|
111 |
$step = filter_input(INPUT_POST, WPRSS_INTRO_STEP_POST_PARAM, FILTER_VALIDATE_INT);
|
@@ -117,9 +95,9 @@ add_action('wp_ajax_wprss_set_intro_step', function () {
|
|
117 |
}
|
118 |
|
119 |
wprss_set_intro_step($step);
|
120 |
-
wprss_ajax_success_response(
|
121 |
'wprss_intro_step' => $step,
|
122 |
-
|
123 |
});
|
124 |
|
125 |
/**
|
@@ -130,9 +108,9 @@ add_action('wp_ajax_wprss_set_intro_step', function () {
|
|
130 |
add_action('wp_ajax_wprss_create_intro_feed', function () {
|
131 |
check_ajax_referer(WPRSS_INTRO_NONCE_NAME, 'nonce');
|
132 |
if (!current_user_can('manage_options')) {
|
133 |
-
wp_die('', '',
|
134 |
'response' => 403,
|
135 |
-
|
136 |
}
|
137 |
|
138 |
$url = filter_input(INPUT_POST, WPRSS_INTRO_FEED_URL_PARAM, FILTER_VALIDATE_URL);
|
@@ -149,11 +127,11 @@ add_action('wp_ajax_wprss_create_intro_feed', function () {
|
|
149 |
}
|
150 |
|
151 |
try {
|
152 |
-
wp_schedule_single_event(time(), 'wprss_create_intro_feed_source',
|
153 |
$items = wprss_preview_feed_items($url);
|
154 |
-
$data =
|
155 |
'feed_items' => $items,
|
156 |
-
|
157 |
wprss_set_intro_done(true);
|
158 |
wprss_ajax_success_response($data);
|
159 |
} catch (Exception $e) {
|
@@ -175,9 +153,9 @@ add_action('init', function () {
|
|
175 |
|
176 |
check_admin_referer(WPRSS_INTRO_NONCE_NAME, 'nonce');
|
177 |
if (!current_user_can('manage_options')) {
|
178 |
-
wp_die('', '',
|
179 |
'response' => 403,
|
180 |
-
|
181 |
}
|
182 |
|
183 |
try {
|
@@ -219,15 +197,15 @@ function wprss_preview_feed_items($url, $max = 10)
|
|
219 |
}
|
220 |
|
221 |
$count = 0;
|
222 |
-
$results =
|
223 |
foreach ($items as $item) {
|
224 |
/* @var $item SimplePie_Item */
|
225 |
-
$results[] =
|
226 |
'title' => $item->get_title(),
|
227 |
'permalink' => $item->get_permalink(),
|
228 |
'date' => $item->get_date(get_option('date_format')),
|
229 |
'author' => $item->get_author()->name,
|
230 |
-
|
231 |
|
232 |
if ($count++ > $max) {
|
233 |
break;
|
@@ -263,15 +241,15 @@ function wprss_create_intro_feed_source($url)
|
|
263 |
}
|
264 |
|
265 |
// Update the existing feed source with a new generated name and new URL
|
266 |
-
wp_update_post(
|
267 |
'ID' => $feedId,
|
268 |
'post_title' => wprss_feed_source_name_from_url($url),
|
269 |
'post_status' => 'publish',
|
270 |
-
'meta_input' =>
|
271 |
'wprss_url' => $url,
|
272 |
'wprss_limit' => WPRSS_INTRO_FEED_LIMIT
|
273 |
-
|
274 |
-
|
275 |
|
276 |
// Re-import the items for this feed
|
277 |
wprss_delete_feed_items($feedId);
|
@@ -294,7 +272,7 @@ function wprss_create_intro_feed_source($url)
|
|
294 |
function wprss_create_feed_source_with_url($url)
|
295 |
{
|
296 |
$name = wprss_feed_source_name_from_url($url);
|
297 |
-
$result = wprss_import_feed_sources_array(
|
298 |
|
299 |
if (empty($result)) {
|
300 |
throw new Exception(
|
@@ -385,12 +363,12 @@ function wprss_create_shortcode_page($title = null, $status = 'draft')
|
|
385 |
? _x('Feeds', 'default name of shortcode page', WPRSS_TEXT_DOMAIN)
|
386 |
: $title;
|
387 |
|
388 |
-
$id = wp_insert_post(
|
389 |
'post_type' => 'page',
|
390 |
'post_title' => $title,
|
391 |
'post_content' => '[wp-rss-aggregator]',
|
392 |
-
'post_status' => $status
|
393 |
-
|
394 |
|
395 |
if (is_wp_error($id)) {
|
396 |
throw new Exception($id->get_error_message(), $id->get_error_code());
|
@@ -443,9 +421,9 @@ function wprss_get_intro_page_url()
|
|
443 |
*
|
444 |
* @return bool True if the introduction should be shown, false if not.
|
445 |
*/
|
446 |
-
function
|
447 |
{
|
448 |
-
return wprss_is_new_user() && intval(get_option(WPRSS_INTRO_DID_INTRO_OPTION, 0)) !== 1 &&
|
449 |
}
|
450 |
|
451 |
/**
|
@@ -483,14 +461,14 @@ function wprss_is_new_user()
|
|
483 |
* @param array $data Optional data to send.
|
484 |
* @param int $status Optional HTTP status code of the response.
|
485 |
*/
|
486 |
-
function wprss_ajax_success_response($data =
|
487 |
{
|
488 |
-
echo json_encode(
|
489 |
'success' => true,
|
490 |
'error' => '',
|
491 |
'data' => $data,
|
492 |
'status' => $status,
|
493 |
-
|
494 |
wp_die();
|
495 |
}
|
496 |
|
@@ -504,11 +482,11 @@ function wprss_ajax_success_response($data = [], $status = 200)
|
|
504 |
*/
|
505 |
function wprss_ajax_error_response($message, $status = 400)
|
506 |
{
|
507 |
-
echo json_encode(
|
508 |
'success' => false,
|
509 |
'error' => $message,
|
510 |
-
'data' =>
|
511 |
'status' => $status,
|
512 |
-
|
513 |
wp_die();
|
514 |
}
|
17 |
define('WPRSS_INTRO_SHORTCODE_PAGE_OPTION', 'wprss_intro_shortcode_page');
|
18 |
define('WPRSS_INTRO_SHORTCODE_PAGE_PREVIEW_PARAM', 'wprss_preview_shortcode_page');
|
19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
/**
|
21 |
* Registers the introduction page.
|
22 |
*
|
27 |
null,
|
28 |
__('Welcome to WP RSS Aggregator'),
|
29 |
__('Welcome to WP RSS Aggregator'),
|
30 |
+
'manage_options',
|
31 |
WPRSS_INTRO_PAGE_SLUG,
|
32 |
+
'wprss_render_intro_page'
|
33 |
);
|
34 |
});
|
35 |
|
42 |
* @throws Twig_Error_Runtime
|
43 |
* @throws Twig_Error_Syntax
|
44 |
*/
|
45 |
+
function wprss_render_intro_page()
|
46 |
{
|
47 |
+
wprss_update_previous_update_page_version();
|
48 |
+
|
49 |
+
wprss_plugin_enqueue_app_scripts('intro-wizard', WPRSS_JS . 'intro.min.js', array(), '0.1', true);
|
50 |
wp_enqueue_style('intro-wizard', WPRSS_CSS . 'intro.min.css');
|
51 |
|
52 |
$nonce = wp_create_nonce(WPRSS_INTRO_NONCE_NAME);
|
53 |
+
wp_localize_script('intro-wizard', 'wprssWizardConfig', array(
|
54 |
'previewUrl' => admin_url('admin.php?wprss_preview_shortcode_page=1&nonce=' . $nonce),
|
55 |
'feedListUrl' => admin_url('edit.php?post_type=wprss_feed'),
|
56 |
'addOnsUrl' => 'https://www.wprssaggregator.com/plugins/?utm_source=core_plugin&utm_medium=onboarding_wizard&utm_campaign=onboarding_wizard_addons_button&utm_content=addons_button',
|
58 |
'demoImageUrl' => WPRSS_IMG . 'welcome-page/demo.png',
|
59 |
'feedbackUrl' => 'https://wordpress.org/support/topic/does-everything-i-need-16/',
|
60 |
'knowledgeBaseUrl' => 'https://kb.wprssaggregator.com/',
|
61 |
+
'feedEndpoint' => array(
|
62 |
'url' => admin_url('admin-ajax.php'),
|
63 |
+
'defaultPayload' => array(
|
64 |
'action' => 'wprss_create_intro_feed',
|
65 |
'nonce' => $nonce,
|
66 |
+
),
|
67 |
+
),
|
68 |
+
));
|
69 |
|
70 |
+
echo wprss_render_template('admin-intro-page.twig', array(
|
71 |
'title' => 'Welcome to WP RSS Aggregator 👋',
|
72 |
'subtitle' => 'Follow these introductory steps to get started with WP RSS Aggregator.',
|
73 |
+
));
|
74 |
}
|
75 |
|
76 |
/**
|
81 |
add_action('wp_ajax_wprss_set_intro_step', function () {
|
82 |
check_ajax_referer(WPRSS_INTRO_NONCE_NAME, 'nonce');
|
83 |
if (!current_user_can('manage_options')) {
|
84 |
+
wp_die('', '', array(
|
85 |
'response' => 403,
|
86 |
+
));
|
87 |
}
|
88 |
|
89 |
$step = filter_input(INPUT_POST, WPRSS_INTRO_STEP_POST_PARAM, FILTER_VALIDATE_INT);
|
95 |
}
|
96 |
|
97 |
wprss_set_intro_step($step);
|
98 |
+
wprss_ajax_success_response(array(
|
99 |
'wprss_intro_step' => $step,
|
100 |
+
));
|
101 |
});
|
102 |
|
103 |
/**
|
108 |
add_action('wp_ajax_wprss_create_intro_feed', function () {
|
109 |
check_ajax_referer(WPRSS_INTRO_NONCE_NAME, 'nonce');
|
110 |
if (!current_user_can('manage_options')) {
|
111 |
+
wp_die('', '', array(
|
112 |
'response' => 403,
|
113 |
+
));
|
114 |
}
|
115 |
|
116 |
$url = filter_input(INPUT_POST, WPRSS_INTRO_FEED_URL_PARAM, FILTER_VALIDATE_URL);
|
127 |
}
|
128 |
|
129 |
try {
|
130 |
+
wp_schedule_single_event(time(), 'wprss_create_intro_feed_source', array($url));
|
131 |
$items = wprss_preview_feed_items($url);
|
132 |
+
$data = array(
|
133 |
'feed_items' => $items,
|
134 |
+
);
|
135 |
wprss_set_intro_done(true);
|
136 |
wprss_ajax_success_response($data);
|
137 |
} catch (Exception $e) {
|
153 |
|
154 |
check_admin_referer(WPRSS_INTRO_NONCE_NAME, 'nonce');
|
155 |
if (!current_user_can('manage_options')) {
|
156 |
+
wp_die('', '', array(
|
157 |
'response' => 403,
|
158 |
+
));
|
159 |
}
|
160 |
|
161 |
try {
|
197 |
}
|
198 |
|
199 |
$count = 0;
|
200 |
+
$results = array();
|
201 |
foreach ($items as $item) {
|
202 |
/* @var $item SimplePie_Item */
|
203 |
+
$results[] = array(
|
204 |
'title' => $item->get_title(),
|
205 |
'permalink' => $item->get_permalink(),
|
206 |
'date' => $item->get_date(get_option('date_format')),
|
207 |
'author' => $item->get_author()->name,
|
208 |
+
);
|
209 |
|
210 |
if ($count++ > $max) {
|
211 |
break;
|
241 |
}
|
242 |
|
243 |
// Update the existing feed source with a new generated name and new URL
|
244 |
+
wp_update_post(array(
|
245 |
'ID' => $feedId,
|
246 |
'post_title' => wprss_feed_source_name_from_url($url),
|
247 |
'post_status' => 'publish',
|
248 |
+
'meta_input' => array(
|
249 |
'wprss_url' => $url,
|
250 |
'wprss_limit' => WPRSS_INTRO_FEED_LIMIT
|
251 |
+
)
|
252 |
+
));
|
253 |
|
254 |
// Re-import the items for this feed
|
255 |
wprss_delete_feed_items($feedId);
|
272 |
function wprss_create_feed_source_with_url($url)
|
273 |
{
|
274 |
$name = wprss_feed_source_name_from_url($url);
|
275 |
+
$result = wprss_import_feed_sources_array(array($url => $name));
|
276 |
|
277 |
if (empty($result)) {
|
278 |
throw new Exception(
|
363 |
? _x('Feeds', 'default name of shortcode page', WPRSS_TEXT_DOMAIN)
|
364 |
: $title;
|
365 |
|
366 |
+
$id = wp_insert_post(array(
|
367 |
'post_type' => 'page',
|
368 |
'post_title' => $title,
|
369 |
'post_content' => '[wp-rss-aggregator]',
|
370 |
+
'post_status' => $status,
|
371 |
+
));
|
372 |
|
373 |
if (is_wp_error($id)) {
|
374 |
throw new Exception($id->get_error_message(), $id->get_error_code());
|
421 |
*
|
422 |
* @return bool True if the introduction should be shown, false if not.
|
423 |
*/
|
424 |
+
function wprss_should_do_intro_page()
|
425 |
{
|
426 |
+
return wprss_is_new_user() && intval(get_option(WPRSS_INTRO_DID_INTRO_OPTION, 0)) !== 1 && current_user_can('manage_options');
|
427 |
}
|
428 |
|
429 |
/**
|
461 |
* @param array $data Optional data to send.
|
462 |
* @param int $status Optional HTTP status code of the response.
|
463 |
*/
|
464 |
+
function wprss_ajax_success_response($data = array(), $status = 200)
|
465 |
{
|
466 |
+
echo json_encode(array(
|
467 |
'success' => true,
|
468 |
'error' => '',
|
469 |
'data' => $data,
|
470 |
'status' => $status,
|
471 |
+
));
|
472 |
wp_die();
|
473 |
}
|
474 |
|
482 |
*/
|
483 |
function wprss_ajax_error_response($message, $status = 400)
|
484 |
{
|
485 |
+
echo json_encode(array(
|
486 |
'success' => false,
|
487 |
'error' => $message,
|
488 |
+
'data' => array(),
|
489 |
'status' => $status,
|
490 |
+
));
|
491 |
wp_die();
|
492 |
}
|
includes/admin-options.php
CHANGED
@@ -355,8 +355,6 @@
|
|
355 |
function wprss_settings_page_display() {
|
356 |
?>
|
357 |
<div class="wrap">
|
358 |
-
<?php screen_icon( 'wprss-aggregator' ); ?>
|
359 |
-
|
360 |
<h2><?php _e( 'WP RSS Aggregator Settings', WPRSS_TEXT_DOMAIN ); ?></h2>
|
361 |
|
362 |
<?php settings_errors(); ?>
|
355 |
function wprss_settings_page_display() {
|
356 |
?>
|
357 |
<div class="wrap">
|
|
|
|
|
358 |
<h2><?php _e( 'WP RSS Aggregator Settings', WPRSS_TEXT_DOMAIN ); ?></h2>
|
359 |
|
360 |
<?php settings_errors(); ?>
|
includes/admin-plugins.php
ADDED
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if (!defined('ABSPATH')) {
|
4 |
+
die;
|
5 |
+
}
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Adds deactivate poll application on plugin's page.
|
9 |
+
*
|
10 |
+
* @since 4.12.1
|
11 |
+
*/
|
12 |
+
add_action('admin_init', function () {
|
13 |
+
$page = trim($_SERVER["REQUEST_URI"], '/');
|
14 |
+
$isPluginsPage = strpos($page, 'plugins.php') !== false;
|
15 |
+
|
16 |
+
if (!$isPluginsPage) {
|
17 |
+
return;
|
18 |
+
}
|
19 |
+
|
20 |
+
add_action('admin_footer', function () {
|
21 |
+
wprss_plugin_enqueue_app_scripts('wpra-plugins', WPRSS_JS . 'plugins.min.js', array(), '0.1', true);
|
22 |
+
wp_enqueue_style('wpra-plugins', WPRSS_CSS . 'plugins.min.css');
|
23 |
+
|
24 |
+
$addons = wprss_find_installed_addon_names();
|
25 |
+
$addons = array_fill_keys($addons, 1);
|
26 |
+
|
27 |
+
wp_localize_script('wpra-plugins', 'WrpaDisablePoll', array(
|
28 |
+
'image' => WPRSS_IMG,
|
29 |
+
'url' => 'https://hooks.zapier.com/hooks/catch/305784/puf5uf/',
|
30 |
+
'model' => array(
|
31 |
+
'reason' => 'Other',
|
32 |
+
'follow_up' => null,
|
33 |
+
'date' => date('j M Y'),
|
34 |
+
'addons' => $addons,
|
35 |
+
),
|
36 |
+
'form' => array(
|
37 |
+
array(
|
38 |
+
'label' => '',
|
39 |
+
'type' => 'radio',
|
40 |
+
'name' => 'reason',
|
41 |
+
'options' =>
|
42 |
+
array(
|
43 |
+
array(
|
44 |
+
'value' => 'I no longer need the plugin',
|
45 |
+
'label' => __('I no longer need the plugin', WPRSS_TEXT_DOMAIN),
|
46 |
+
),
|
47 |
+
array(
|
48 |
+
'value' => 'I found a better alternative',
|
49 |
+
'label' => __('I found a better alternative', WPRSS_TEXT_DOMAIN),
|
50 |
+
),
|
51 |
+
array(
|
52 |
+
'value' => 'I couldn\'t get the plugin to work',
|
53 |
+
'label' => __('I couldn\'t get the plugin to work', WPRSS_TEXT_DOMAIN),
|
54 |
+
),
|
55 |
+
array(
|
56 |
+
'value' => 'I\'m temporarily deactivating the plugin, but I\'ll be back',
|
57 |
+
'label' => __('I\'m temporarily deactivating the plugin, but I\'ll be back', WPRSS_TEXT_DOMAIN),
|
58 |
+
),
|
59 |
+
array(
|
60 |
+
'value' => 'I have a WP RSS Aggregator add-on',
|
61 |
+
'label' => __('I have a WP RSS Aggregator add-on', WPRSS_TEXT_DOMAIN),
|
62 |
+
),
|
63 |
+
array(
|
64 |
+
'value' => 'Other',
|
65 |
+
'label' => __('Other', WPRSS_TEXT_DOMAIN),
|
66 |
+
),
|
67 |
+
),
|
68 |
+
),
|
69 |
+
array(
|
70 |
+
'label' => __('Would you mind sharing its name?', WPRSS_TEXT_DOMAIN),
|
71 |
+
'type' => 'textarea',
|
72 |
+
'name' => 'follow_up',
|
73 |
+
'condition' =>
|
74 |
+
array(
|
75 |
+
'field' => 'reason',
|
76 |
+
'operator' => '=',
|
77 |
+
'value' => 'I found a better alternative',
|
78 |
+
),
|
79 |
+
),
|
80 |
+
array(
|
81 |
+
'type' => 'content',
|
82 |
+
'label' => __('Have you <a target="_blank" href="https://wordpress.org/support/plugin/wp-rss-aggregator/">contacted our support team</a> or checked out our <a href="https://kb.wprssaggregator.com/" target="_blank">Knowledge Base</a>?', WPRSS_TEXT_DOMAIN),
|
83 |
+
'condition' =>
|
84 |
+
array(
|
85 |
+
'field' => 'reason',
|
86 |
+
'operator' => '=',
|
87 |
+
'value' => 'I couldn\'t get the plugin to work',
|
88 |
+
),
|
89 |
+
),
|
90 |
+
array(
|
91 |
+
'type' => 'content',
|
92 |
+
'className' => 'error',
|
93 |
+
'label' => __('This core plugin is required for all our premium add-ons. Please don\'t deactivate it if you currently have premium add-ons installed and activated.', WPRSS_TEXT_DOMAIN),
|
94 |
+
'condition' =>
|
95 |
+
array(
|
96 |
+
'field' => 'reason',
|
97 |
+
'operator' => '=',
|
98 |
+
'value' => 'I have a WP RSS Aggregator add-on',
|
99 |
+
),
|
100 |
+
),
|
101 |
+
array(
|
102 |
+
'label' => __('Please share your reason...', WPRSS_TEXT_DOMAIN),
|
103 |
+
'type' => 'textarea',
|
104 |
+
'name' => 'follow_up',
|
105 |
+
'condition' =>
|
106 |
+
array(
|
107 |
+
'field' => 'reason',
|
108 |
+
'operator' => '=',
|
109 |
+
'value' => 'Other',
|
110 |
+
),
|
111 |
+
),
|
112 |
+
)
|
113 |
+
));
|
114 |
+
|
115 |
+
echo '<div id="wpra-plugins-app"></div>';
|
116 |
+
});
|
117 |
+
});
|
includes/admin-update-page.php
ADDED
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
define('WPRSS_UPDATE_PAGE_SLUG', 'wpra-update');
|
4 |
+
define('WPRSS_UPDATE_PAGE_PREV_VERSION_OPTION', 'wprss_prev_update_page_version');
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Registers the update page.
|
8 |
+
*
|
9 |
+
* @since 4.12.1
|
10 |
+
*/
|
11 |
+
add_action('admin_menu', function () {
|
12 |
+
add_submenu_page(
|
13 |
+
null,
|
14 |
+
__('Thank you for updating WP RSS Aggregator', WPRSS_TEXT_DOMAIN),
|
15 |
+
__('Thank you for updating WP RSS Aggregator', WPRSS_TEXT_DOMAIN),
|
16 |
+
'manage_options',
|
17 |
+
WPRSS_UPDATE_PAGE_SLUG,
|
18 |
+
'wprss_render_update_page'
|
19 |
+
);
|
20 |
+
});
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Renders the update page.
|
24 |
+
*
|
25 |
+
* @since 4.12.1
|
26 |
+
*
|
27 |
+
* @throws Twig_Error_Loader
|
28 |
+
* @throws Twig_Error_Runtime
|
29 |
+
* @throws Twig_Error_Syntax
|
30 |
+
*/
|
31 |
+
function wprss_render_update_page()
|
32 |
+
{
|
33 |
+
wprss_update_previous_update_page_version();
|
34 |
+
|
35 |
+
wp_enqueue_style('update-page', WPRSS_CSS . 'update.min.css');
|
36 |
+
|
37 |
+
echo wprss_render_template('admin-update-page.twig', array(
|
38 |
+
'title' => __('What\'s new in WP RSS Aggregator?', WPRSS_TEXT_DOMAIN),
|
39 |
+
'version' => WPRSS_VERSION,
|
40 |
+
'beacon_nonce_field' => wp_nonce_field('wprss_hs_beacon_enabled'),
|
41 |
+
'beacon_enabled' => wprss_is_help_beacon_enabled(),
|
42 |
+
'url' => array(
|
43 |
+
'main' => admin_url('edit.php?post_type=wprss_feed'),
|
44 |
+
'website' => 'https://www.wprssaggregator.com/',
|
45 |
+
'support' => 'https://www.wprssaggregator.com/contact/',
|
46 |
+
'kb' => 'https://kb.wprssaggregator.com/',
|
47 |
+
),
|
48 |
+
'path' => array(
|
49 |
+
'images' => WPRSS_IMG,
|
50 |
+
),
|
51 |
+
));
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Retrieves the URL of the update page.
|
56 |
+
*
|
57 |
+
* @since 4.12.1
|
58 |
+
*
|
59 |
+
* @return string
|
60 |
+
*/
|
61 |
+
function wprss_get_update_page_url()
|
62 |
+
{
|
63 |
+
return menu_page_url(WPRSS_UPDATE_PAGE_SLUG, false);
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Checks whether the update should be shown or not, based on whether the user is new and previously had an older
|
68 |
+
* version of the plugin.
|
69 |
+
*
|
70 |
+
* @since 4.12.1
|
71 |
+
*
|
72 |
+
* @return bool True if the update page should be shown, false if not.
|
73 |
+
*/
|
74 |
+
function wprss_should_do_update_page()
|
75 |
+
{
|
76 |
+
return !wprss_is_new_user() && current_user_can('manage_options') && wprss_user_had_previous_version();
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Checks whether the user had a previous version of WP RSS Aggregator.
|
81 |
+
*
|
82 |
+
* @since 4.12.1
|
83 |
+
*
|
84 |
+
* @return mixed
|
85 |
+
*/
|
86 |
+
function wprss_user_had_previous_version()
|
87 |
+
{
|
88 |
+
$previous = wprss_get_previous_update_page_version();
|
89 |
+
$is_newer = version_compare(WPRSS_VERSION, $previous, '>');
|
90 |
+
|
91 |
+
return $is_newer;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Updates the previous update page version to the current plugin version.
|
96 |
+
*
|
97 |
+
* @since 4.12.1
|
98 |
+
*/
|
99 |
+
function wprss_update_previous_update_page_version()
|
100 |
+
{
|
101 |
+
update_option(WPRSS_UPDATE_PAGE_PREV_VERSION_OPTION, WPRSS_VERSION);
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Retrieves the previous update page version seen by the user, if at all.
|
106 |
+
*
|
107 |
+
* @since 4.12.1
|
108 |
+
*
|
109 |
+
* @return string The version string, or '0.0.0' if the user is new nad has not used WPRA before.
|
110 |
+
*/
|
111 |
+
function wprss_get_previous_update_page_version()
|
112 |
+
{
|
113 |
+
wprss_migrate_welcome_page_to_update_page();
|
114 |
+
|
115 |
+
return get_option(WPRSS_UPDATE_PAGE_PREV_VERSION_OPTION, '0.0.0');
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Migrates the previously used "welcome screen" version DB option.
|
120 |
+
*
|
121 |
+
* @since 4.12.1
|
122 |
+
*/
|
123 |
+
function wprss_migrate_welcome_page_to_update_page()
|
124 |
+
{
|
125 |
+
// Get the previous welcome screen version - for when the page was called the "welcome screen"
|
126 |
+
$pwsv = get_option('wprss_pwsv', null);
|
127 |
+
|
128 |
+
// If the option exists, move it to the new option
|
129 |
+
if ($pwsv !== null) {
|
130 |
+
update_option(WPRSS_UPDATE_PAGE_PREV_VERSION_OPTION, $pwsv);
|
131 |
+
delete_option('wprss_pwsv');
|
132 |
+
}
|
133 |
+
}
|
includes/admin.php
CHANGED
@@ -115,3 +115,46 @@
|
|
115 |
}
|
116 |
return $action_links;
|
117 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
}
|
116 |
return $action_links;
|
117 |
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Function for registering application's scripts that depends on advanced libraries.
|
121 |
+
* It will enqueue manifest and vendor scripts, which contains all required logic
|
122 |
+
* for bootstrapping application and dependencies.
|
123 |
+
*
|
124 |
+
* Use only for Vue-related apps that use Webpack for being built.
|
125 |
+
*
|
126 |
+
* @since 4.12.1
|
127 |
+
*
|
128 |
+
* @param $handle
|
129 |
+
* @param string $src
|
130 |
+
* @param array $deps
|
131 |
+
* @param bool $ver
|
132 |
+
* @param bool $in_footer
|
133 |
+
*/
|
134 |
+
function wprss_plugin_enqueue_app_scripts( $handle, $src = '', $deps = array(), $ver = false, $in_footer = false ) {
|
135 |
+
/*
|
136 |
+
* Manifest file holds function used for bootstrapping and ordered
|
137 |
+
* loading of dependencies and application.
|
138 |
+
*/
|
139 |
+
wp_enqueue_script('wpra-manifest', WPRSS_JS . 'wpra-manifest.min.js', array(), '0.1', true);
|
140 |
+
|
141 |
+
/*
|
142 |
+
* Vendor file holds all common dependencies for "compilable" applications.
|
143 |
+
*
|
144 |
+
* For example, `intro` pages application's and plugin's page application's files
|
145 |
+
* holds only logic for that particular application. Common dependencies like Vue
|
146 |
+
* live in this file and loaded before that application.
|
147 |
+
*/
|
148 |
+
wp_enqueue_script('wpra-vendor', WPRSS_JS . 'wpra-vendor.min.js', array(
|
149 |
+
'wpra-manifest'
|
150 |
+
), '0.1', true);
|
151 |
+
|
152 |
+
/*
|
153 |
+
* Enqueue requested script.
|
154 |
+
*/
|
155 |
+
$deps = array_merge(array(
|
156 |
+
'wpra-manifest',
|
157 |
+
'wpra-vendor',
|
158 |
+
), $deps);
|
159 |
+
wp_enqueue_script($handle, $src, $deps, $ver, $in_footer);
|
160 |
+
}
|
includes/custom-feed.php
CHANGED
@@ -13,13 +13,9 @@
|
|
13 |
* @since 3.3
|
14 |
*/
|
15 |
function wprss_addfeed_add_feed() {
|
16 |
-
$
|
17 |
-
if (
|
18 |
-
$url =
|
19 |
-
}
|
20 |
-
else {
|
21 |
-
$url = $general_settings['custom_feed_url'] = 'wprss';
|
22 |
-
update_option( 'wprss_settings_general', $general_settings );
|
23 |
}
|
24 |
|
25 |
// Add the feed
|
13 |
* @since 3.3
|
14 |
*/
|
15 |
function wprss_addfeed_add_feed() {
|
16 |
+
$url = wprss_get_general_setting('custom_feed_url');
|
17 |
+
if (empty($url)) {
|
18 |
+
$url = 'wprss';
|
|
|
|
|
|
|
|
|
19 |
}
|
20 |
|
21 |
// Add the feed
|
includes/custom-post-types.php
CHANGED
@@ -99,7 +99,8 @@ define('WPRSS_POST_TYPE_FEED_SOURCE', 'wprss_feed');
|
|
99 |
'slug' => 'feed-items',
|
100 |
'with_front' => false,
|
101 |
),
|
102 |
-
'capability_type' => '
|
|
|
103 |
'labels' => $labels
|
104 |
)
|
105 |
);
|
99 |
'slug' => 'feed-items',
|
100 |
'with_front' => false,
|
101 |
),
|
102 |
+
'capability_type' => 'feed_item',
|
103 |
+
'map_meta_cap' => true,
|
104 |
'labels' => $labels
|
105 |
)
|
106 |
);
|
includes/feed-importing.php
CHANGED
@@ -745,8 +745,6 @@
|
|
745 |
usort($items, function ($itemA, $itemB) use ($comparators, $feedSource) {
|
746 |
return wprss_items_sort_compare_items($itemA, $itemB, $comparators, $feedSource);
|
747 |
});
|
748 |
-
|
749 |
-
wprss_log_obj( 'Sorted', NULL, WPRSS_LOG_LEVEL_INFO );
|
750 |
} catch (\InvalidArgumentException $e) {
|
751 |
wprss_log( 'Error was encountered while sorting items; list remains unsorted', NULL, WPRSS_LOG_LEVEL_WARNING );
|
752 |
}
|
745 |
usort($items, function ($itemA, $itemB) use ($comparators, $feedSource) {
|
746 |
return wprss_items_sort_compare_items($itemA, $itemB, $comparators, $feedSource);
|
747 |
});
|
|
|
|
|
748 |
} catch (\InvalidArgumentException $e) {
|
749 |
wprss_log( 'Error was encountered while sorting items; list remains unsorted', NULL, WPRSS_LOG_LEVEL_WARNING );
|
750 |
}
|
includes/licensing.php
CHANGED
@@ -59,6 +59,39 @@ function wprss_get_addons($noCache = false) {
|
|
59 |
: $addons;
|
60 |
}
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
/**
|
63 |
* Hooks the licensing system into WordPress.
|
64 |
*/
|
59 |
: $addons;
|
60 |
}
|
61 |
|
62 |
+
/**
|
63 |
+
* Finds all WPRA addons installed, even if they are deactivated.
|
64 |
+
*
|
65 |
+
* @since 4.12.1
|
66 |
+
*
|
67 |
+
* @return array An array of WordPress plugin info arrays.
|
68 |
+
*/
|
69 |
+
function wprss_find_installed_addons()
|
70 |
+
{
|
71 |
+
$all_plugins = get_plugins();
|
72 |
+
$addons = array();
|
73 |
+
foreach ($all_plugins as $plugin_path => $plugin) {
|
74 |
+
if ($plugin_path !== WPRSS_FILE_CONSTANT && strpos($plugin['Name'], 'WP RSS Aggregator - ') === 0) {
|
75 |
+
$addons[$plugin_path] = $plugin;
|
76 |
+
}
|
77 |
+
}
|
78 |
+
return $addons;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Retrieves the names of the installed addons, even if they are deactivated.
|
83 |
+
*
|
84 |
+
* @since 4.12.1
|
85 |
+
*
|
86 |
+
* @return string[] A list of the names of installed addons.
|
87 |
+
*/
|
88 |
+
function wprss_find_installed_addon_names()
|
89 |
+
{
|
90 |
+
return array_map(function ($plugin_info) {
|
91 |
+
return substr($plugin_info['Name'], strlen('WP RSS Aggregator - '));
|
92 |
+
}, wprss_find_installed_addons());
|
93 |
+
}
|
94 |
+
|
95 |
/**
|
96 |
* Hooks the licensing system into WordPress.
|
97 |
*/
|
includes/opml-importer.php
CHANGED
@@ -60,9 +60,9 @@
|
|
60 |
*/
|
61 |
public function opml_import() {
|
62 |
// Show the Icon and Title
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
|
67 |
// Get the current step from URL query string
|
68 |
$step = empty( $_GET['step'] ) ? 0 : (int) $_GET['step'];
|
60 |
*/
|
61 |
public function opml_import() {
|
62 |
// Show the Icon and Title
|
63 |
+
?>
|
64 |
+
<div class="wrap">
|
65 |
+
<h2><?php _e( 'Import OPML', WPRSS_TEXT_DOMAIN ) ?></h2><?php
|
66 |
|
67 |
// Get the current step from URL query string
|
68 |
$step = empty( $_GET['step'] ) ? 0 : (int) $_GET['step'];
|
includes/roles-capabilities.php
CHANGED
@@ -45,7 +45,7 @@
|
|
45 |
function wprss_get_core_caps() {
|
46 |
$capabilities = array();
|
47 |
|
48 |
-
$capability_types = array( 'feed', '
|
49 |
|
50 |
foreach ( $capability_types as $capability_type ) {
|
51 |
$capabilities[ $capability_type ] = array(
|
@@ -104,4 +104,4 @@
|
|
104 |
}
|
105 |
}
|
106 |
}
|
107 |
-
}
|
45 |
function wprss_get_core_caps() {
|
46 |
$capabilities = array();
|
47 |
|
48 |
+
$capability_types = array( 'feed', 'feed_item' );
|
49 |
|
50 |
foreach ( $capability_types as $capability_type ) {
|
51 |
$capabilities[ $capability_type ] = array(
|
104 |
}
|
105 |
}
|
106 |
}
|
107 |
+
}
|
includes/scripts.php
CHANGED
@@ -5,6 +5,8 @@
|
|
5 |
* @package WPRSSAggregator
|
6 |
*/
|
7 |
|
|
|
|
|
8 |
add_action( 'init', 'wprss_register_scripts', 9 );
|
9 |
function wprss_register_scripts()
|
10 |
{
|
@@ -71,6 +73,11 @@
|
|
71 |
'sent-error' => sprintf(__('There was an error sending the form. Please use the <a href="%s">contact form on our site.</a>', WPRSS_TEXT_DOMAIN), esc_attr('https://www.wprssaggregator.com/contact/')),
|
72 |
'sent-ok' => __("Your message has been sent and we'll send you a confirmation e-mail when we receive it.", WPRSS_TEXT_DOMAIN)
|
73 |
));
|
|
|
|
|
|
|
|
|
|
|
74 |
}
|
75 |
|
76 |
|
@@ -156,6 +163,11 @@
|
|
156 |
wp_enqueue_script( 'wprss-admin-help' );
|
157 |
}
|
158 |
|
|
|
|
|
|
|
|
|
|
|
159 |
do_action('wprss_admin_exclusive_scripts_styles');
|
160 |
}
|
161 |
|
@@ -214,5 +226,6 @@
|
|
214 |
wp_register_style( 'wprss-admin-editor-styles', WPRSS_CSS . 'admin-editor.css', array(), $version );
|
215 |
wp_register_style( 'wprss-admin-tracking-styles', WPRSS_CSS . 'admin-tracking-styles.css', array(), $version );
|
216 |
wp_register_style( 'wprss-admin-general-styles', WPRSS_CSS . 'admin-general-styles.css', array(), $version );
|
|
|
217 |
wp_register_style( 'jquery-style', 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css', array(), $version );
|
218 |
}
|
5 |
* @package WPRSSAggregator
|
6 |
*/
|
7 |
|
8 |
+
use Aventura\Wprss\Core\Licensing\License\Status as License_Status;
|
9 |
+
|
10 |
add_action( 'init', 'wprss_register_scripts', 9 );
|
11 |
function wprss_register_scripts()
|
12 |
{
|
73 |
'sent-error' => sprintf(__('There was an error sending the form. Please use the <a href="%s">contact form on our site.</a>', WPRSS_TEXT_DOMAIN), esc_attr('https://www.wprssaggregator.com/contact/')),
|
74 |
'sent-ok' => __("Your message has been sent and we'll send you a confirmation e-mail when we receive it.", WPRSS_TEXT_DOMAIN)
|
75 |
));
|
76 |
+
|
77 |
+
wp_register_script( 'wprss-hs-beacon-js', WPRSS_JS . 'beacon.min.js', array(), $version );
|
78 |
+
wp_localize_script( 'wprss-hs-beacon-js', 'WprssHelpBeaconConfig', array (
|
79 |
+
'premiumSupport' => ( wprss_licensing_get_manager()->licenseWithStatusExists( License_Status::VALID ) )
|
80 |
+
));
|
81 |
}
|
82 |
|
83 |
|
163 |
wp_enqueue_script( 'wprss-admin-help' );
|
164 |
}
|
165 |
|
166 |
+
if (wprss_is_help_beacon_enabled()) {
|
167 |
+
wp_enqueue_script('wprss-hs-beacon-js');
|
168 |
+
wp_enqueue_style('wprss-hs-beacon-css');
|
169 |
+
}
|
170 |
+
|
171 |
do_action('wprss_admin_exclusive_scripts_styles');
|
172 |
}
|
173 |
|
226 |
wp_register_style( 'wprss-admin-editor-styles', WPRSS_CSS . 'admin-editor.css', array(), $version );
|
227 |
wp_register_style( 'wprss-admin-tracking-styles', WPRSS_CSS . 'admin-tracking-styles.css', array(), $version );
|
228 |
wp_register_style( 'wprss-admin-general-styles', WPRSS_CSS . 'admin-general-styles.css', array(), $version );
|
229 |
+
wp_register_style( 'wprss-hs-beacon-css', WPRSS_CSS, 'beacon.css', array(), $version );
|
230 |
wp_register_style( 'jquery-style', 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css', array(), $version );
|
231 |
}
|
includes/secure-reset.php
CHANGED
@@ -45,6 +45,8 @@
|
|
45 |
delete_option( 'wprss_addon_notices' );
|
46 |
delete_option( 'wprss_settings_notices' );
|
47 |
delete_option( 'wprss_pwsv' );
|
|
|
|
|
48 |
}
|
49 |
|
50 |
// Deactivate the plugin
|
@@ -53,4 +55,4 @@
|
|
53 |
deactivate_plugins( WPRSS_FILE_CONSTANT, TRUE );
|
54 |
}
|
55 |
|
56 |
-
}
|
45 |
delete_option( 'wprss_addon_notices' );
|
46 |
delete_option( 'wprss_settings_notices' );
|
47 |
delete_option( 'wprss_pwsv' );
|
48 |
+
delete_option( WPRSS_UPDATE_PAGE_PREV_VERSION_OPTION );
|
49 |
+
delete_option( WPRSS_INTRO_DID_INTRO_OPTION );
|
50 |
}
|
51 |
|
52 |
// Deactivate the plugin
|
55 |
deactivate_plugins( WPRSS_FILE_CONSTANT, TRUE );
|
56 |
}
|
57 |
|
58 |
+
}
|
includes/twig.php
CHANGED
@@ -10,7 +10,7 @@ define('WPRSS_TWIG_MIN_PHP_VERSION', '5.4.0');
|
|
10 |
/**
|
11 |
* Returns whether twig can be used.
|
12 |
*
|
13 |
-
* @since
|
14 |
*
|
15 |
* @return bool True if twig can be used, false if not.
|
16 |
*/
|
@@ -33,7 +33,7 @@ function wprss_twig()
|
|
33 |
if ($twig === null) {
|
34 |
$options = array();
|
35 |
|
36 |
-
if (defined('WP_DEBUG')
|
37 |
$options['cache'] = get_temp_dir() . 'wprss/twig-cache';
|
38 |
}
|
39 |
|
10 |
/**
|
11 |
* Returns whether twig can be used.
|
12 |
*
|
13 |
+
* @since 4.12.1
|
14 |
*
|
15 |
* @return bool True if twig can be used, false if not.
|
16 |
*/
|
33 |
if ($twig === null) {
|
34 |
$options = array();
|
35 |
|
36 |
+
if (!defined('WP_DEBUG') || !WP_DEBUG) {
|
37 |
$options['cache'] = get_temp_dir() . 'wprss/twig-cache';
|
38 |
}
|
39 |
|
js/beacon.min.js
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
!function(e,t,n){function a(){var e=t.getElementsByTagName("script")[0],n=t.createElement("script");n.type="text/javascript",n.async=!0,n.src="https://beacon-v2.helpscout.net",e.parentNode.insertBefore(n,e)}if(e.Beacon=n=function(t,n,a){e.Beacon.readyQueue.push({method:t,options:n,data:a})},n.readyQueue=[],"complete"===t.readyState)return a();e.attachEvent?e.attachEvent("onload",a):e.addEventListener("load",a,!1)}(window,document,window.Beacon||function(){});
|
2 |
+
window.Beacon('init', 'af457a55-16ed-412d-95e9-c84417562092');
|
3 |
+
window.Beacon('config', {
|
4 |
+
messagingEnabled: WprssHelpBeaconConfig.premiumSupport
|
5 |
+
});
|
js/intro.min.js
CHANGED
@@ -1,6 +1 @@
|
|
1 |
-
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var n=t();for(var r in n)("object"==typeof exports?exports:e)[r]=n[r]}}("undefined"!=typeof self?self:this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,t),i.l=!0,i.exports}var n={};return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=1)}([function(e,t){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";function r(e,t,n,r,i,o,a,s){var c="function"==typeof e?e.options:e;t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),r&&(c.functional=!0),o&&(c._scopeId="data-v-"+o);var u;if(a?(u=function(e){e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,e||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),i&&i.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(a)},c._ssrRegister=u):i&&(u=s?function(){i.call(this,this.$root.$options.shadowRoot)}:i),u)if(c.functional){c._injectStyles=u;var l=c.render;c.render=function(e,t){return u.call(t),l(e,t)}}else{var f=c.beforeCreate;c.beforeCreate=f?[].concat(f,u):[u]}return{exports:e,options:c}}function i(e,t){for(var n=(arguments.length>2&&void 0!==arguments[2]&&arguments[2],new FormData),r=Object.keys(t),i=Array.isArray(r),o=0,r=i?r:r[Symbol.iterator]();;){var a;if(i){if(o>=r.length)break;a=r[o++]}else{if(o=r.next(),o.done)break;a=o.value}var s=a;n.set(s,t[s])}return fetch(e,{method:"post",body:n}).then(function(e){return e.json()}).then(function(e){if(200!==e.status)throw e;return e})}function o(e){return e&&DataView.prototype.isPrototypeOf(e)}function a(e){if("string"!=typeof e&&(e=String(e)),/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(e))throw new TypeError("Invalid character in header field name");return e.toLowerCase()}function s(e){return"string"!=typeof e&&(e=String(e)),e}function c(e){var t={next:function(){var t=e.shift();return{done:void 0===t,value:t}}};return H.iterable&&(t[Symbol.iterator]=function(){return t}),t}function u(e){this.map={},e instanceof u?e.forEach(function(e,t){this.append(t,e)},this):Array.isArray(e)?e.forEach(function(e){this.append(e[0],e[1])},this):e&&Object.getOwnPropertyNames(e).forEach(function(t){this.append(t,e[t])},this)}function l(e){if(e.bodyUsed)return Promise.reject(new TypeError("Already read"));e.bodyUsed=!0}function f(e){return new Promise(function(t,n){e.onload=function(){t(e.result)},e.onerror=function(){n(e.error)}})}function d(e){var t=new FileReader,n=f(t);return t.readAsArrayBuffer(e),n}function p(e){var t=new FileReader,n=f(t);return t.readAsText(e),n}function v(e){for(var t=new Uint8Array(e),n=new Array(t.length),r=0;r<t.length;r++)n[r]=String.fromCharCode(t[r]);return n.join("")}function h(e){if(e.slice)return e.slice(0);var t=new Uint8Array(e.byteLength);return t.set(new Uint8Array(e)),t.buffer}function m(){return this.bodyUsed=!1,this._initBody=function(e){this._bodyInit=e,e?"string"==typeof e?this._bodyText=e:H.blob&&Blob.prototype.isPrototypeOf(e)?this._bodyBlob=e:H.formData&&FormData.prototype.isPrototypeOf(e)?this._bodyFormData=e:H.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)?this._bodyText=e.toString():H.arrayBuffer&&H.blob&&o(e)?(this._bodyArrayBuffer=h(e.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer])):H.arrayBuffer&&(ArrayBuffer.prototype.isPrototypeOf(e)||V(e))?this._bodyArrayBuffer=h(e):this._bodyText=e=Object.prototype.toString.call(e):this._bodyText="",this.headers.get("content-type")||("string"==typeof e?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type?this.headers.set("content-type",this._bodyBlob.type):H.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)&&this.headers.set("content-type","application/x-www-form-urlencoded;charset=UTF-8"))},H.blob&&(this.blob=function(){var e=l(this);if(e)return e;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){return this._bodyArrayBuffer?l(this)||Promise.resolve(this._bodyArrayBuffer):this.blob().then(d)}),this.text=function(){var e=l(this);if(e)return e;if(this._bodyBlob)return p(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(v(this._bodyArrayBuffer));if(this._bodyFormData)throw new Error("could not read FormData body as text");return Promise.resolve(this._bodyText)},H.formData&&(this.formData=function(){return this.text().then(_)}),this.json=function(){return this.text().then(JSON.parse)},this}function y(e){var t=e.toUpperCase();return q.indexOf(t)>-1?t:e}function g(e,t){t=t||{};var n=t.body;if(e instanceof g){if(e.bodyUsed)throw new TypeError("Already read");this.url=e.url,this.credentials=e.credentials,t.headers||(this.headers=new u(e.headers)),this.method=e.method,this.mode=e.mode,this.signal=e.signal,n||null==e._bodyInit||(n=e._bodyInit,e.bodyUsed=!0)}else this.url=String(e);if(this.credentials=t.credentials||this.credentials||"same-origin",!t.headers&&this.headers||(this.headers=new u(t.headers)),this.method=y(t.method||this.method||"GET"),this.mode=t.mode||this.mode||null,this.signal=t.signal||this.signal,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&n)throw new TypeError("Body not allowed for GET or HEAD requests");this._initBody(n)}function _(e){var t=new FormData;return e.trim().split("&").forEach(function(e){if(e){var n=e.split("="),r=n.shift().replace(/\+/g," "),i=n.join("=").replace(/\+/g," ");t.append(decodeURIComponent(r),decodeURIComponent(i))}}),t}function b(e){var t=new u;return e.replace(/\r?\n[\t ]+/g," ").split(/\r?\n/).forEach(function(e){var n=e.split(":"),r=n.shift().trim();if(r){var i=n.join(":").trim();t.append(r,i)}}),t}function w(e,t){t||(t={}),this.type="default",this.status=void 0===t.status?200:t.status,this.ok=this.status>=200&&this.status<300,this.statusText="statusText"in t?t.statusText:"OK",this.headers=new u(t.headers),this.url=t.url||"",this._initBody(e)}function C(e,t){return new Promise(function(n,r){function i(){a.abort()}var o=new g(e,t);if(o.signal&&o.signal.aborted)return r(new W("Aborted","AbortError"));var a=new XMLHttpRequest;a.onload=function(){var e={status:a.status,statusText:a.statusText,headers:b(a.getAllResponseHeaders()||"")};e.url="responseURL"in a?a.responseURL:e.headers.get("X-Request-URL");var t="response"in a?a.response:a.responseText;n(new w(t,e))},a.onerror=function(){r(new TypeError("Network request failed"))},a.ontimeout=function(){r(new TypeError("Network request failed"))},a.onabort=function(){r(new W("Aborted","AbortError"))},a.open(o.method,o.url,!0),"include"===o.credentials?a.withCredentials=!0:"omit"===o.credentials&&(a.withCredentials=!1),"responseType"in a&&H.blob&&(a.responseType="blob"),o.headers.forEach(function(e,t){a.setRequestHeader(t,e)}),o.signal&&(o.signal.addEventListener("abort",i),a.onreadystatechange=function(){4===a.readyState&&o.signal.removeEventListener("abort",i)}),a.send(void 0===o._bodyInit?null:o._bodyInit)})}Object.defineProperty(t,"__esModule",{value:!0});var x=n(3),$=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"wizard-holder animated fadeIn"},[n("div",{staticClass:"connect-steps"},[n("div",{staticClass:"step-items"},[n("div",{staticClass:"step-progress",class:"step-progress--"+e.activeScreenIndex}),e._v(" "),e._l(e.screens,function(t,r){return n("div",{staticClass:"step-item",class:{"step-item_active":e.active(t.id),"step-item_completed":t.completed()&&r<e.activeScreenIndex}},[n("div",{staticClass:"step-item__status"},[t.completed()&&r<e.activeScreenIndex?n("span",{staticClass:"dashicons dashicons-yes"}):e._e()]),e._v(" "),n("div",{staticClass:"step-item__info"},[n("div",{staticClass:"step-item__title"},[e._v(e._s(t.title))]),e._v(" "),t.description?n("div",{staticClass:"step-item__description"},[e._v(e._s(t.description))]):e._e()])])})],2)]),e._v(" "),n("div",{staticClass:"wizard"},[n("transition",{attrs:{name:e.transition,mode:"out-in"}},[e.active("feed")?n("div",{key:e.activeScreen,staticClass:"wizard_content"},[n("div",{staticClass:"wizard_hello"},[e._v("\n Enter your first RSS Feed URL\n ")]),e._v(" "),n("form",{staticClass:"wizard_info",attrs:{id:"feedForm"},on:{submit:function(t){return t.preventDefault(),e.next(t)}}},[n("div",{staticClass:"form-group"},[n("input",{directives:[{name:"model",rawName:"v-model",value:e.form.feedSourceUrl,expression:"form.feedSourceUrl"}],staticClass:"wpra-feed-input",attrs:{type:"text",placeholder:"https://www.sourcedomain.com/feed/"},domProps:{value:e.form.feedSourceUrl},on:{input:function(t){t.target.composing||e.$set(e.form,"feedSourceUrl",t.target.value)}}}),e._v(" "),e.isFeedError?n("span",{staticClass:"dashicons dashicons-warning warning-icon"}):e._e(),e._v(" "),e.isFeedError?n("a",{attrs:{href:e.validateLink,target:"_blank"}},[e._v("Validate feed")]):e._e()])]),e._v(" "),e.isFeedError?n("div",{staticClass:"wizard_error"},[n("p",[e._v("This RSS feed URL appears to be invalid. Here are a couple of things you can try:")]),e._v(" "),n("ol",[n("li",[e._v('Check whether the URL you entered is the correct one by trying one of the options when clicking on "How do I find an RSS feed URL?" below.')]),e._v(" "),n("li",[e._v("\n Test out this other RSS feed URL to make sure the plugin is working correctly - https://www.wpmayor.com/feed/ - If it works, you may "),n("a",{attrs:{href:e.supportUrl,target:"_blank"}},[e._v("contact us here")]),e._v(" to help you with your source.\n ")]),e._v(" "),n("li",[e._v("Test the URL's validity by W3C standards, the standards we use in our plugins, using the “Validate feed” link above.")])])]):e._e(),e._v(" "),n("expander",{attrs:{title:"How do I find an RSS feed URL?"}},[n("p",[e._v("WP RSS Aggregator fetches feed items through RSS feeds. Almost every website in the world provides an RSS feed. Here's how to find it:")]),e._v(" "),n("p",[e._v("Option 1: Add /feed to the website's homepage URL ")]),e._v(" "),n("p",[e._v("Many sites have their RSS feed at the same URL. For instance, if the website's URL is www.thiswebsite.com, then the RSS feed could be at www.thiswebsite.com/feed.")]),e._v(" "),n("p",[e._v("Option 2: Look for the RSS share icon")]),e._v(" "),n("p",[e._v("Many websites have share icons on their pages for Facebook, Twitter and more. Many times, there will also be an orange RSS icon. Click on that to access the RSS feed URL.")]),e._v(" "),n("p",[e._v("Option 3: Browser RSS Auto-Discovery")]),e._v(" "),n("p",[e._v("Most browsers either include an RSS auto-discovery tool by default or they allow you to add extensions for it. Firefox shows an RSS icon above the website, in the address bar, which you can click on directly. Chrome offers extensions such as this one.")]),e._v(" "),n("p",[e._v("Option 4: Look at the Page Source")]),e._v(" "),n("p",[e._v('When on any page of the website you\'re looking to import feed items from, right click and press "View Page Source". Once the new window opens, use the “Find” feature (Ctrl-F on PC, Command-F on Mac) and search for " RSS". This should take you to a line that reads like this (or similar):')]),e._v(" "),n("p",[n("code",[e._v('\n <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="https://www.sourcedomain.com/feed/" />\n ')])]),e._v(" "),n("p",[e._v("The RSS feed’s URL is found between the quotes after href=. In the above case, it would be https://www.sourcedomain.com/feed/.")]),e._v(" "),n("p",[n("a",{attrs:{href:e.knowledgeBaseUrl,target:"_blank"}},[e._v("Browse our Knowledge Base for more information.")])])])],1):e._e(),e._v(" "),e.active("feedItems")?n("div",{key:e.activeScreen,staticClass:"wizard_content"},[n("div",{staticClass:"wizard_hello"},[e._v("\n Latest feed items from your selected feed source:\n ")]),e._v(" "),n("div",{staticClass:"wpra-feed-items"},e._l(e.feed.items,function(t){return n("div",{staticClass:"wpra-feed-item"},[n("div",{staticClass:"wpra-feed-item__link"},[n("a",{attrs:{href:t.permalink,target:"_blank"}},[e._v(e._s(t.title))])]),e._v(" "),n("div",{staticClass:"wpra-feed-item__info"},[e._v("\n Published on "+e._s(t.date)+" | By "+e._s(t.author)+"\n ")])])}),0),e._v(" "),n("div",{staticClass:"wizard_label"},[e._v("\n Copy and paste this shortcode to any page or post to display the full list:\n ")]),e._v(" "),n("div",{staticClass:"wrpa-shortcode"},[n("div",{staticClass:"wrpa-shortcode-form",on:{click:function(t){e.copyToClipboard()}}},[n("input",{ref:"selected",staticClass:"wrpa-shortcode-form__shortcode",attrs:{type:"text",readonly:"",value:"[wp-rss-aggregator]"}}),e._v(" "),n("div",{staticClass:"wrpa-shortcode-form__button"},[e._v("\n Ctrl+C or CMD+C to copy\n ")])]),e._v("\n OR\n "),n("a",{attrs:{href:e.previewUrl,target:"_blank"}},[e._v("Preview the feed items on a new page")])])]):e._e(),e._v(" "),e.active("finish")?n("div",{key:e.activeScreen,staticClass:"wizard_content"},[n("div",{staticClass:"wizard_hello"},[e._v("\n You’ve successfully set up your first feed source 😄\n ")]),e._v(" "),n("div",{staticClass:"wpra-cols-title"},[e._v("\n Do more with WP RSS Aggregator - here is what we did at CryptoHeadlines.com.\n ")]),e._v(" "),n("div",{staticClass:"wpra-cols"},[n("div",{staticClass:"col"},[n("p",[e._v("CryptoHeadlines.com displays latest news, Youtube videos, podcasts, jobs and more from the Cryptocurrency industry.")]),e._v(" "),n("p",[e._v("It uses Feed to Post to import articles, Youtube videos, and podcast links.")]),e._v(" "),n("p",[e._v("Full Text RSS Feeds is used to fetch the full content of the job listings to present more information to the potential applicant.")]),e._v(" "),n("p",[e._v("Keyword Filtering is used to filter out content that contains profanity and keywords or phrases deemed as inappropriate.")]),e._v(" "),n("div",{staticStyle:{"margin-bottom":".5rem"}},[n("a",{staticClass:"button",attrs:{href:e.addOnsUrl,target:"_blank"}},[e._v("\n Browse Add-ons ⭐️\n ")])]),e._v(" "),n("div",[n("a",{staticStyle:{"font-size":".9em"},attrs:{href:e.supportUrl,target:"_blank"}},[e._v("Contact support for more information.")])])]),e._v(" "),n("div",{staticClass:"col"},[n("img",{staticClass:"img wpra-demo-photo",attrs:{src:e.demoImageUrl}}),e._v(" "),n("div",{staticClass:"wpra-feedback"},[n("div",{staticClass:"wpra-feedback__copy"},[n("div",{staticClass:"wpra-feedback__text"},[e._v("\n This plugin has made my life a lot easier, and the support has been great as well.\n ")]),e._v(" "),n("div",{staticClass:"wpra-feedback__rating"},[n("span",{staticClass:"dashicons dashicons-star-filled"}),e._v(" "),n("span",{staticClass:"dashicons dashicons-star-filled"}),e._v(" "),n("span",{staticClass:"dashicons dashicons-star-filled"}),e._v(" "),n("span",{staticClass:"dashicons dashicons-star-filled"}),e._v(" "),n("span",{staticClass:"dashicons dashicons-star-filled"})]),e._v(" "),n("div",{staticClass:"wpra-feedback__by"},[n("a",{attrs:{href:e.feedbackUrl,target:"_blank"}},[e._v("\n Review by officeinnovator\n ")])])])])])])]):e._e()]),e._v(" "),n("div",{staticClass:"connect-actions pad"},[n("div",{staticClass:"pad-item--grow"},[e.active("finish")?e._e():n("button",{staticClass:"button-clear",on:{click:e.finish}},[e._v("\n Skip the introduction\n ")])]),e._v(" "),n("div",{staticClass:"pad-item--no-shrink"},[e.isBackAvailable?n("button",{staticClass:"button-clear",on:{click:e.back}},[e._v("\n Back\n ")]):e._e(),e._v(" "),n("button",{staticClass:"button button-primary button-large",class:{"loading-button":e.isLoading},on:{click:e.next}},[e._v("\n "+e._s(e.active("finish")?"Continue to Plugin":"Next")+"\n ")])])])],1)])},k=[],S=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"wpra-expander",class:{"wpra-expander--expanded":e.isExpanded}},[n("div",{staticClass:"wpra-expander__title",on:{click:function(t){e.isExpanded=!e.isExpanded}}},[e._v("\n "+e._s(e.title)+"\n "),n("span",{staticClass:"dashicons dashicons-arrow-down-alt2"})]),e._v(" "),n("transition-expand",[e.isExpanded?n("div",[n("div",{staticClass:"wpra-expander__content"},[e._t("default")],2)]):e._e()])],1)},A=[],T={name:"TransitionExpand",functional:!0,render:function(e,t){return e("transition",{props:{name:"expand"},on:{afterEnter:function(e){e.style.height="auto"},enter:function(e){var t=getComputedStyle(e),n=t.width;e.style.width=n,e.style.position="absolute",e.style.visibility="hidden",e.style.height="auto";var r=getComputedStyle(e),i=r.height;e.style.width=null,e.style.position=null,e.style.visibility=null,e.style.height=0,getComputedStyle(e).height,setTimeout(function(){e.style.height=i})},leave:function(e){var t=getComputedStyle(e),n=t.height;e.style.height=n,getComputedStyle(e).height,setTimeout(function(){e.style.height=0})}}},t.children)}},O=T,E=r(O,void 0,void 0,!1,null,null,null);E.options.__file="TransitionExpand.vue";var I=E.exports,L={data:function(){return{isExpanded:this.defaultExpanded}},props:{title:{},defaultExpanded:{value:!1}},components:{TransitionExpand:I}},j=L,P=r(j,S,A,!1,null,null,null);P.options.__file="Expander.vue";var R=P.exports,N=function(e){return e},D=window.wprssWizardConfig,U={data:function(){var e=this;return{prevHeight:0,screens:[{id:"feed",title:N("Add feed source URL"),description:!1,next:this.submitFeed,completed:function(){return e.feed.items.length},entered:function(){e.focusOnInput("feed")}},{id:"feedItems",title:N("Display feed items"),description:!1,next:this.continueItems,entered:function(){setTimeout(function(){e.copyToClipboard()},400)},completed:function(){return e.feed.items.length&&e.itemsPassed}},{id:"finish",title:N("Complete introduction"),description:!1,next:this.completeIntroduction,completed:function(){return e.feed.items.length&&e.itemsPassed}}],transition:"slide-up",activeScreen:"feed",form:{feedSourceUrl:null},itemsPassed:!1,stepLoading:!1,isLoading:!1,isFeedError:!1,feed:{items:[]},previewUrl:D.previewUrl,addOnsUrl:D.addOnsUrl,supportUrl:D.supportUrl,demoImageUrl:D.demoImageUrl,feedbackUrl:D.feedbackUrl,knowledgeBaseUrl:D.knowledgeBaseUrl}},computed:{validateLink:function(){return"https://validator.w3.org/feed/check.cgi?url="+encodeURI(this.form.feedSourceUrl)},activeScreenIndex:function(){var e=this;return this.screens.findIndex(function(t){return t.id===e.activeScreen})},currentScreen:function(){var e=this;return this.screens.find(function(t){return t.id===e.activeScreen})},actionCompleted:function(){return this.currentScreen.completed()},isBackAvailable:function(){return this.activeScreenIndex>0&&this.activeScreenIndex<this.screens.length}},mounted:function(){this.onScreenEnter()},methods:{submitFeed:function(){var e=this,t=Object.assign(D.feedEndpoint.defaultPayload,{wprss_intro_feed_url:this.form.feedSourceUrl});return this.isLoading=!0,this.isFeedError=!1,i(D.feedEndpoint.url,t).then(function(t){return e.feed.items=t.data.feed_items.slice(0,3),e.isLoading=!1,{}}).catch(function(t){throw e.isLoading=!1,e.isFeedError=!0,t})},continueItems:function(){return this.itemsPassed=!0,Promise.resolve({})},completeIntroduction:function(){return Promise.resolve({})},next:function(){var e=this;this.transition="slide-up";var t=this.currentScreen.next?this.currentScreen.next:function(){return Promise.resolve(!1)};this.stepLoading=!0,t().then(function(t){e.stepLoading=!1},function(e){throw e}).then(function(){var t=e.activeScreenIndex+1;t>=e.screens.length?e.finish():(e.activeScreen=e.screens[t].id,e.onScreenEnter())}).catch(function(e){console.error(e)})},onScreenEnter:function(){var e=this;this.$nextTick(function(){e.currentScreen.entered&&e.currentScreen.entered()})},focusOnInput:function(e){if(!this.$refs[e]||!this.$refs[e].focus)return!1;this.$refs[e].focus()},back:function(){this.transition="slide-down",this.activeScreen=this.screens[this.activeScreenIndex-1].id},finish:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=function(){return window.location.href=D.feedListUrl};if(e)return void(confirm("Are you sure you want to skip the introduction?")&&t());t()},active:function(e){return this.activeScreen===e},copyToClipboard:function(){try{this.$refs.selected.focus(),this.$refs.selected.select()}catch(e){console.error(e)}}},components:{Expander:R}},F=U,M=r(F,$,k,!1,null,null,null);M.options.__file="Wizard.vue";var B=M.exports,H={searchParams:"URLSearchParams"in self,iterable:"Symbol"in self&&"iterator"in Symbol,blob:"FileReader"in self&&"Blob"in self&&function(){try{return new Blob,!0}catch(e){return!1}}(),formData:"FormData"in self,arrayBuffer:"ArrayBuffer"in self};if(H.arrayBuffer)var z=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],V=ArrayBuffer.isView||function(e){return e&&z.indexOf(Object.prototype.toString.call(e))>-1};u.prototype.append=function(e,t){e=a(e),t=s(t);var n=this.map[e];this.map[e]=n?n+", "+t:t},u.prototype.delete=function(e){delete this.map[a(e)]},u.prototype.get=function(e){return e=a(e),this.has(e)?this.map[e]:null},u.prototype.has=function(e){return this.map.hasOwnProperty(a(e))},u.prototype.set=function(e,t){this.map[a(e)]=s(t)},u.prototype.forEach=function(e,t){for(var n in this.map)this.map.hasOwnProperty(n)&&e.call(t,this.map[n],n,this)},u.prototype.keys=function(){var e=[];return this.forEach(function(t,n){e.push(n)}),c(e)},u.prototype.values=function(){var e=[];return this.forEach(function(t){e.push(t)}),c(e)},u.prototype.entries=function(){var e=[];return this.forEach(function(t,n){e.push([n,t])}),c(e)},H.iterable&&(u.prototype[Symbol.iterator]=u.prototype.entries);var q=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];g.prototype.clone=function(){return new g(this,{body:this._bodyInit})},m.call(g.prototype),m.call(w.prototype),w.prototype.clone=function(){return new w(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new u(this.headers),url:this.url})},w.error=function(){var e=new w(null,{status:0,statusText:""});return e.type="error",e};var K=[301,302,303,307,308];w.redirect=function(e,t){if(-1===K.indexOf(t))throw new RangeError("Invalid status code");return new w(null,{status:t,headers:{location:e}})};var W=self.DOMException;try{new W}catch(e){W=function(e,t){this.message=e,this.name=t;var n=Error(e);this.stack=n.stack},W.prototype=Object.create(Error.prototype),W.prototype.constructor=W}C.polyfill=!0,self.fetch||(self.fetch=C,self.Headers=u,self.Request=g,self.Response=w),n(2),new x.a({el:"#wpra-wizard-app",template:"<Wizard/>",components:{Wizard:B}})},function(e,t){},function(e,t,n){"use strict";(function(e,n){function r(e){return void 0===e||null===e}function i(e){return void 0!==e&&null!==e}function o(e){return!0===e}function a(e){return!1===e}function s(e){return"string"==typeof e||"number"==typeof e||"symbol"==typeof e||"boolean"==typeof e}function c(e){return null!==e&&"object"==typeof e}function u(e){return"[object Object]"===fo.call(e)}function l(e){return"[object RegExp]"===fo.call(e)}function f(e){var t=parseFloat(String(e));return t>=0&&Math.floor(t)===t&&isFinite(e)}function d(e){return null==e?"":"object"==typeof e?JSON.stringify(e,null,2):String(e)}function p(e){var t=parseFloat(e);return isNaN(t)?e:t}function v(e,t){for(var n=Object.create(null),r=e.split(","),i=0;i<r.length;i++)n[r[i]]=!0;return t?function(e){return n[e.toLowerCase()]}:function(e){return n[e]}}function h(e,t){if(e.length){var n=e.indexOf(t);if(n>-1)return e.splice(n,1)}}function m(e,t){return ho.call(e,t)}function y(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}}function g(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n}function _(e,t){return e.bind(t)}function b(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function w(e,t){for(var n in t)e[n]=t[n];return e}function C(e){for(var t={},n=0;n<e.length;n++)e[n]&&w(t,e[n]);return t}function x(e,t,n){}function $(e,t){if(e===t)return!0;var n=c(e),r=c(t);if(!n||!r)return!n&&!r&&String(e)===String(t);try{var i=Array.isArray(e),o=Array.isArray(t);if(i&&o)return e.length===t.length&&e.every(function(e,n){return $(e,t[n])});if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(i||o)return!1;var a=Object.keys(e),s=Object.keys(t);return a.length===s.length&&a.every(function(n){return $(e[n],t[n])})}catch(e){return!1}}function k(e,t){for(var n=0;n<e.length;n++)if($(e[n],t))return n;return-1}function S(e){var t=!1;return function(){t||(t=!0,e.apply(this,arguments))}}function A(e){var t=(e+"").charCodeAt(0);return 36===t||95===t}function T(e,t,n,r){Object.defineProperty(e,t,{value:n,enumerable:!!r,writable:!0,configurable:!0})}function O(e){if(!To.test(e)){var t=e.split(".");return function(e){for(var n=0;n<t.length;n++){if(!e)return;e=e[t[n]]}return e}}}function E(e){return"function"==typeof e&&/native code/.test(e.toString())}function I(e){Go.push(e),Jo.target=e}function L(){Go.pop(),Jo.target=Go[Go.length-1]}function j(e){return new Xo(void 0,void 0,void 0,String(e))}function P(e){var t=new Xo(e.tag,e.data,e.children&&e.children.slice(),e.text,e.elm,e.context,e.componentOptions,e.asyncFactory);return t.ns=e.ns,t.isStatic=e.isStatic,t.key=e.key,t.isComment=e.isComment,t.fnContext=e.fnContext,t.fnOptions=e.fnOptions,t.fnScopeId=e.fnScopeId,t.asyncMeta=e.asyncMeta,t.isCloned=!0,t}function R(e){na=e}function N(e,t){e.__proto__=t}function D(e,t,n){for(var r=0,i=n.length;r<i;r++){var o=n[r];T(e,o,t[o])}}function U(e,t){if(c(e)&&!(e instanceof Xo)){var n;return m(e,"__ob__")&&e.__ob__ instanceof ra?n=e.__ob__:na&&!zo()&&(Array.isArray(e)||u(e))&&Object.isExtensible(e)&&!e._isVue&&(n=new ra(e)),t&&n&&n.vmCount++,n}}function F(e,t,n,r,i){var o=new Jo,a=Object.getOwnPropertyDescriptor(e,t);if(!a||!1!==a.configurable){var s=a&&a.get,c=a&&a.set;s&&!c||2!==arguments.length||(n=e[t]);var u=!i&&U(n);Object.defineProperty(e,t,{enumerable:!0,configurable:!0,get:function(){var t=s?s.call(e):n;return Jo.target&&(o.depend(),u&&(u.dep.depend(),Array.isArray(t)&&H(t))),t},set:function(t){var r=s?s.call(e):n;t===r||t!==t&&r!==r||s&&!c||(c?c.call(e,t):n=t,u=!i&&U(t),o.notify())}})}}function M(e,t,n){if(Array.isArray(e)&&f(t))return e.length=Math.max(e.length,t),e.splice(t,1,n),n;if(t in e&&!(t in Object.prototype))return e[t]=n,n;var r=e.__ob__;return e._isVue||r&&r.vmCount?n:r?(F(r.value,t,n),r.dep.notify(),n):(e[t]=n,n)}function B(e,t){if(Array.isArray(e)&&f(t))return void e.splice(t,1);var n=e.__ob__;e._isVue||n&&n.vmCount||m(e,t)&&(delete e[t],n&&n.dep.notify())}function H(e){for(var t=void 0,n=0,r=e.length;n<r;n++)t=e[n],t&&t.__ob__&&t.__ob__.dep.depend(),Array.isArray(t)&&H(t)}function z(e,t){if(!t)return e;for(var n,r,i,o=Object.keys(t),a=0;a<o.length;a++)n=o[a],r=e[n],i=t[n],m(e,n)?r!==i&&u(r)&&u(i)&&z(r,i):M(e,n,i);return e}function V(e,t,n){return n?function(){var r="function"==typeof t?t.call(n,n):t,i="function"==typeof e?e.call(n,n):e;return r?z(r,i):i}:t?e?function(){return z("function"==typeof t?t.call(this,this):t,"function"==typeof e?e.call(this,this):e)}:t:e}function q(e,t){var n=t?e?e.concat(t):Array.isArray(t)?t:[t]:e;return n?K(n):n}function K(e){for(var t=[],n=0;n<e.length;n++)-1===t.indexOf(e[n])&&t.push(e[n]);return t}function W(e,t,n,r){var i=Object.create(e||null);return t?w(i,t):i}function J(e,t){var n=e.props;if(n){var r,i,o,a={};if(Array.isArray(n))for(r=n.length;r--;)"string"==typeof(i=n[r])&&(o=yo(i),a[o]={type:null});else if(u(n))for(var s in n)i=n[s],o=yo(s),a[o]=u(i)?i:{type:i};e.props=a}}function G(e,t){var n=e.inject;if(n){var r=e.inject={};if(Array.isArray(n))for(var i=0;i<n.length;i++)r[n[i]]={from:n[i]};else if(u(n))for(var o in n){var a=n[o];r[o]=u(a)?w({from:o},a):{from:a}}}}function X(e){var t=e.directives;if(t)for(var n in t){var r=t[n];"function"==typeof r&&(t[n]={bind:r,update:r})}}function Z(e,t,n){function r(r){var i=ia[r]||sa;s[r]=i(e[r],t[r],n,r)}if("function"==typeof t&&(t=t.options),J(t,n),G(t,n),X(t),!t._base&&(t.extends&&(e=Z(e,t.extends,n)),t.mixins))for(var i=0,o=t.mixins.length;i<o;i++)e=Z(e,t.mixins[i],n);var a,s={};for(a in e)r(a);for(a in t)m(e,a)||r(a);return s}function Y(e,t,n,r){if("string"==typeof n){var i=e[t];if(m(i,n))return i[n];var o=yo(n);if(m(i,o))return i[o];var a=go(o);return m(i,a)?i[a]:i[n]||i[o]||i[a]}}function Q(e,t,n,r){var i=t[e],o=!m(n,e),a=n[e],s=re(Boolean,i.type);if(s>-1)if(o&&!m(i,"default"))a=!1;else if(""===a||a===bo(e)){var c=re(String,i.type);(c<0||s<c)&&(a=!0)}if(void 0===a){a=ee(r,i,e);var u=na;R(!0),U(a),R(u)}return a}function ee(e,t,n){if(m(t,"default")){var r=t.default;return e&&e.$options.propsData&&void 0===e.$options.propsData[n]&&void 0!==e._props[n]?e._props[n]:"function"==typeof r&&"Function"!==te(t.type)?r.call(e):r}}function te(e){var t=e&&e.toString().match(/^\s*function (\w+)/);return t?t[1]:""}function ne(e,t){return te(e)===te(t)}function re(e,t){if(!Array.isArray(t))return ne(t,e)?0:-1;for(var n=0,r=t.length;n<r;n++)if(ne(t[n],e))return n;return-1}function ie(e,t,n){if(t)for(var r=t;r=r.$parent;){var i=r.$options.errorCaptured;if(i)for(var o=0;o<i.length;o++)try{var a=!1===i[o].call(r,e,t,n);if(a)return}catch(e){oe(e,r,"errorCaptured hook")}}oe(e,t,n)}function oe(e,t,n){if(Ao.errorHandler)try{return Ao.errorHandler.call(null,e,t,n)}catch(e){ae(e,null,"config.errorHandler")}ae(e,t,n)}function ae(e,t,n){if(!Eo&&!Io||"undefined"==typeof console)throw e;console.error(e)}function se(){ua=!1;var e=ca.slice(0);ca.length=0;for(var t=0;t<e.length;t++)e[t]()}function ce(e){return e._withTask||(e._withTask=function(){la=!0;try{return e.apply(null,arguments)}finally{la=!1}})}function ue(e,t){var n;if(ca.push(function(){if(e)try{e.call(t)}catch(e){ie(e,t,"nextTick")}else n&&n(t)}),ua||(ua=!0,la?aa():oa()),!e&&"undefined"!=typeof Promise)return new Promise(function(e){n=e})}function le(e){fe(e,ha),ha.clear()}function fe(e,t){var n,r,i=Array.isArray(e);if(!(!i&&!c(e)||Object.isFrozen(e)||e instanceof Xo)){if(e.__ob__){var o=e.__ob__.dep.id;if(t.has(o))return;t.add(o)}if(i)for(n=e.length;n--;)fe(e[n],t);else for(r=Object.keys(e),n=r.length;n--;)fe(e[r[n]],t)}}function de(e){function t(){var e=arguments,n=t.fns;if(!Array.isArray(n))return n.apply(null,arguments);for(var r=n.slice(),i=0;i<r.length;i++)r[i].apply(null,e)}return t.fns=e,t}function pe(e,t,n,i,a,s){var c,u,l,f;for(c in e)u=e[c],l=t[c],f=ma(c),r(u)||(r(l)?(r(u.fns)&&(u=e[c]=de(u)),o(f.once)&&(u=e[c]=a(f.name,u,f.capture)),n(f.name,u,f.capture,f.passive,f.params)):u!==l&&(l.fns=u,e[c]=l));for(c in t)r(e[c])&&(f=ma(c),i(f.name,t[c],f.capture))}function ve(e,t,n){function a(){n.apply(this,arguments),h(s.fns,a)}e instanceof Xo&&(e=e.data.hook||(e.data.hook={}));var s,c=e[t];r(c)?s=de([a]):i(c.fns)&&o(c.merged)?(s=c,s.fns.push(a)):s=de([c,a]),s.merged=!0,e[t]=s}function he(e,t,n){var o=t.options.props;if(!r(o)){var a={},s=e.attrs,c=e.props;if(i(s)||i(c))for(var u in o){var l=bo(u);me(a,c,u,l,!0)||me(a,s,u,l,!1)}return a}}function me(e,t,n,r,o){if(i(t)){if(m(t,n))return e[n]=t[n],o||delete t[n],!0;if(m(t,r))return e[n]=t[r],o||delete t[r],!0}return!1}function ye(e){for(var t=0;t<e.length;t++)if(Array.isArray(e[t]))return Array.prototype.concat.apply([],e);return e}function ge(e){return s(e)?[j(e)]:Array.isArray(e)?be(e):void 0}function _e(e){return i(e)&&i(e.text)&&a(e.isComment)}function be(e,t){var n,a,c,u,l=[];for(n=0;n<e.length;n++)a=e[n],r(a)||"boolean"==typeof a||(c=l.length-1,u=l[c],Array.isArray(a)?a.length>0&&(a=be(a,(t||"")+"_"+n),_e(a[0])&&_e(u)&&(l[c]=j(u.text+a[0].text),a.shift()),l.push.apply(l,a)):s(a)?_e(u)?l[c]=j(u.text+a):""!==a&&l.push(j(a)):_e(a)&&_e(u)?l[c]=j(u.text+a.text):(o(e._isVList)&&i(a.tag)&&r(a.key)&&i(t)&&(a.key="__vlist"+t+"_"+n+"__"),l.push(a)));return l}function we(e,t){return(e.__esModule||qo&&"Module"===e[Symbol.toStringTag])&&(e=e.default),c(e)?t.extend(e):e}function Ce(e,t,n,r,i){var o=Yo();return o.asyncFactory=e,o.asyncMeta={data:t,context:n,children:r,tag:i},o}function xe(e,t,n){if(o(e.error)&&i(e.errorComp))return e.errorComp;if(i(e.resolved))return e.resolved;if(o(e.loading)&&i(e.loadingComp))return e.loadingComp;if(!i(e.contexts)){var a=e.contexts=[n],s=!0,u=function(e){for(var t=0,n=a.length;t<n;t++)a[t].$forceUpdate();e&&(a.length=0)},l=S(function(n){e.resolved=we(n,t),s?a.length=0:u(!0)}),f=S(function(t){i(e.errorComp)&&(e.error=!0,u(!0))}),d=e(l,f);return c(d)&&("function"==typeof d.then?r(e.resolved)&&d.then(l,f):i(d.component)&&"function"==typeof d.component.then&&(d.component.then(l,f),i(d.error)&&(e.errorComp=we(d.error,t)),i(d.loading)&&(e.loadingComp=we(d.loading,t),0===d.delay?e.loading=!0:setTimeout(function(){r(e.resolved)&&r(e.error)&&(e.loading=!0,u(!1))},d.delay||200)),i(d.timeout)&&setTimeout(function(){r(e.resolved)&&f(null)},d.timeout))),s=!1,e.loading?e.loadingComp:e.resolved}e.contexts.push(n)}function $e(e){return e.isComment&&e.asyncFactory}function ke(e){if(Array.isArray(e))for(var t=0;t<e.length;t++){var n=e[t];if(i(n)&&(i(n.componentOptions)||$e(n)))return n}}function Se(e){e._events=Object.create(null),e._hasHookEvent=!1;var t=e.$options._parentListeners;t&&Ee(e,t)}function Ae(e,t){va.$on(e,t)}function Te(e,t){va.$off(e,t)}function Oe(e,t){var n=va;return function r(){null!==t.apply(null,arguments)&&n.$off(e,r)}}function Ee(e,t,n){va=e,pe(t,n||{},Ae,Te,Oe,e),va=void 0}function Ie(e,t){var n={};if(!e)return n;for(var r=0,i=e.length;r<i;r++){var o=e[r],a=o.data;if(a&&a.attrs&&a.attrs.slot&&delete a.attrs.slot,o.context!==t&&o.fnContext!==t||!a||null==a.slot)(n.default||(n.default=[])).push(o);else{var s=a.slot,c=n[s]||(n[s]=[]);"template"===o.tag?c.push.apply(c,o.children||[]):c.push(o)}}for(var u in n)n[u].every(Le)&&delete n[u];return n}function Le(e){return e.isComment&&!e.asyncFactory||" "===e.text}function je(e,t){t=t||{};for(var n=0;n<e.length;n++)Array.isArray(e[n])?je(e[n],t):t[e[n].key]=e[n].fn;return t}function Pe(e){var t=ya;return ya=e,function(){ya=t}}function Re(e){var t=e.$options,n=t.parent;if(n&&!t.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(e)}e.$parent=n,e.$root=n?n.$root:e,e.$children=[],e.$refs={},e._watcher=null,e._inactive=null,e._directInactive=!1,e._isMounted=!1,e._isDestroyed=!1,e._isBeingDestroyed=!1}function Ne(e,t,n){e.$el=t,e.$options.render||(e.$options.render=Yo),Be(e,"beforeMount");var r;return r=function(){e._update(e._render(),n)},new ka(e,r,x,{before:function(){e._isMounted&&!e._isDestroyed&&Be(e,"beforeUpdate")}},!0),n=!1,null==e.$vnode&&(e._isMounted=!0,Be(e,"mounted")),e}function De(e,t,n,r,i){var o=!!(i||e.$options._renderChildren||r.data.scopedSlots||e.$scopedSlots!==lo);if(e.$options._parentVnode=r,e.$vnode=r,e._vnode&&(e._vnode.parent=r),e.$options._renderChildren=i,e.$attrs=r.data.attrs||lo,e.$listeners=n||lo,t&&e.$options.props){R(!1);for(var a=e._props,s=e.$options._propKeys||[],c=0;c<s.length;c++){var u=s[c],l=e.$options.props;a[u]=Q(u,l,t,e)}R(!0),e.$options.propsData=t}n=n||lo;var f=e.$options._parentListeners;e.$options._parentListeners=n,Ee(e,n,f),o&&(e.$slots=Ie(i,r.context),e.$forceUpdate())}function Ue(e){for(;e&&(e=e.$parent);)if(e._inactive)return!0;return!1}function Fe(e,t){if(t){if(e._directInactive=!1,Ue(e))return}else if(e._directInactive)return;if(e._inactive||null===e._inactive){e._inactive=!1;for(var n=0;n<e.$children.length;n++)Fe(e.$children[n]);Be(e,"activated")}}function Me(e,t){if(!(t&&(e._directInactive=!0,Ue(e))||e._inactive)){e._inactive=!0;for(var n=0;n<e.$children.length;n++)Me(e.$children[n]);Be(e,"deactivated")}}function Be(e,t){I();var n=e.$options[t];if(n)for(var r=0,i=n.length;r<i;r++)try{n[r].call(e)}catch(n){ie(n,e,t+" hook")}e._hasHookEvent&&e.$emit("hook:"+t),L()}function He(){xa=ga.length=_a.length=0,ba={},wa=Ca=!1}function ze(){Ca=!0;var e,t;for(ga.sort(function(e,t){return e.id-t.id}),xa=0;xa<ga.length;xa++)e=ga[xa],e.before&&e.before(),t=e.id,ba[t]=null,e.run();var n=_a.slice(),r=ga.slice();He(),Ke(n),Ve(r),Vo&&Ao.devtools&&Vo.emit("flush")}function Ve(e){for(var t=e.length;t--;){var n=e[t],r=n.vm;r._watcher===n&&r._isMounted&&!r._isDestroyed&&Be(r,"updated")}}function qe(e){e._inactive=!1,_a.push(e)}function Ke(e){for(var t=0;t<e.length;t++)e[t]._inactive=!0,Fe(e[t],!0)}function We(e){var t=e.id;if(null==ba[t]){if(ba[t]=!0,Ca){for(var n=ga.length-1;n>xa&&ga[n].id>e.id;)n--;ga.splice(n+1,0,e)}else ga.push(e);wa||(wa=!0,ue(ze))}}function Je(e,t,n){Sa.get=function(){return this[t][n]},Sa.set=function(e){this[t][n]=e},Object.defineProperty(e,n,Sa)}function Ge(e){e._watchers=[];var t=e.$options;t.props&&Xe(e,t.props),t.methods&&rt(e,t.methods),t.data?Ze(e):U(e._data={},!0),t.computed&&Qe(e,t.computed),t.watch&&t.watch!==Uo&&it(e,t.watch)}function Xe(e,t){var n=e.$options.propsData||{},r=e._props={},i=e.$options._propKeys=[];!e.$parent||R(!1);for(var o in t)!function(o){i.push(o);var a=Q(o,t,n,e);F(r,o,a),o in e||Je(e,"_props",o)}(o);R(!0)}function Ze(e){var t=e.$options.data;t=e._data="function"==typeof t?Ye(t,e):t||{},u(t)||(t={});for(var n=Object.keys(t),r=e.$options.props,i=(e.$options.methods,n.length);i--;){var o=n[i];r&&m(r,o)||A(o)||Je(e,"_data",o)}U(t,!0)}function Ye(e,t){I();try{return e.call(t,t)}catch(e){return ie(e,t,"data()"),{}}finally{L()}}function Qe(e,t){var n=e._computedWatchers=Object.create(null),r=zo();for(var i in t){var o=t[i],a="function"==typeof o?o:o.get;r||(n[i]=new ka(e,a||x,x,Aa)),i in e||et(e,i,o)}}function et(e,t,n){var r=!zo();"function"==typeof n?(Sa.get=r?tt(t):nt(n),Sa.set=x):(Sa.get=n.get?r&&!1!==n.cache?tt(t):nt(n.get):x,Sa.set=n.set||x),Object.defineProperty(e,t,Sa)}function tt(e){return function(){var t=this._computedWatchers&&this._computedWatchers[e];if(t)return t.dirty&&t.evaluate(),Jo.target&&t.depend(),t.value}}function nt(e){return function(){return e.call(this,this)}}function rt(e,t){e.$options.props;for(var n in t)e[n]="function"!=typeof t[n]?x:wo(t[n],e)}function it(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var i=0;i<r.length;i++)ot(e,n,r[i]);else ot(e,n,r)}}function ot(e,t,n,r){return u(n)&&(r=n,n=n.handler),"string"==typeof n&&(n=e[n]),e.$watch(t,n,r)}function at(e){var t=e.$options.provide;t&&(e._provided="function"==typeof t?t.call(e):t)}function st(e){var t=ct(e.$options.inject,e);t&&(R(!1),Object.keys(t).forEach(function(n){F(e,n,t[n])}),R(!0))}function ct(e,t){if(e){for(var n=Object.create(null),r=qo?Reflect.ownKeys(e).filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}):Object.keys(e),i=0;i<r.length;i++){for(var o=r[i],a=e[o].from,s=t;s;){if(s._provided&&m(s._provided,a)){n[o]=s._provided[a];break}s=s.$parent}if(!s&&"default"in e[o]){var c=e[o].default;n[o]="function"==typeof c?c.call(t):c}}return n}}function ut(e,t){var n,r,o,a,s;if(Array.isArray(e)||"string"==typeof e)for(n=new Array(e.length),r=0,o=e.length;r<o;r++)n[r]=t(e[r],r);else if("number"==typeof e)for(n=new Array(e),r=0;r<e;r++)n[r]=t(r+1,r);else if(c(e))for(a=Object.keys(e),n=new Array(a.length),r=0,o=a.length;r<o;r++)s=a[r],n[r]=t(e[s],s,r);return i(n)||(n=[]),n._isVList=!0,n}function lt(e,t,n,r){var i,o=this.$scopedSlots[e];o?(n=n||{},r&&(n=w(w({},r),n)),i=o(n)||t):i=this.$slots[e]||t;var a=n&&n.slot;return a?this.$createElement("template",{slot:a},i):i}function ft(e){return Y(this.$options,"filters",e,!0)||xo}function dt(e,t){return Array.isArray(e)?-1===e.indexOf(t):e!==t}function pt(e,t,n,r,i){var o=Ao.keyCodes[t]||n;return i&&r&&!Ao.keyCodes[t]?dt(i,r):o?dt(o,e):r?bo(r)!==t:void 0}function vt(e,t,n,r,i){if(n&&c(n)){Array.isArray(n)&&(n=C(n));var o;for(var a in n)!function(a){if("class"===a||"style"===a||vo(a))o=e;else{var s=e.attrs&&e.attrs.type;o=r||Ao.mustUseProp(t,s,a)?e.domProps||(e.domProps={}):e.attrs||(e.attrs={})}var c=yo(a);a in o||c in o||(o[a]=n[a],!i)||((e.on||(e.on={}))["update:"+c]=function(e){n[a]=e})}(a)}return e}function ht(e,t){var n=this._staticTrees||(this._staticTrees=[]),r=n[e];return r&&!t?r:(r=n[e]=this.$options.staticRenderFns[e].call(this._renderProxy,null,this),yt(r,"__static__"+e,!1),r)}function mt(e,t,n){return yt(e,"__once__"+t+(n?"_"+n:""),!0),e}function yt(e,t,n){if(Array.isArray(e))for(var r=0;r<e.length;r++)e[r]&&"string"!=typeof e[r]&>(e[r],t+"_"+r,n);else gt(e,t,n)}function gt(e,t,n){e.isStatic=!0,e.key=t,e.isOnce=n}function _t(e,t){if(t&&u(t)){var n=e.on=e.on?w({},e.on):{};for(var r in t){var i=n[r],o=t[r];n[r]=i?[].concat(i,o):o}}return e}function bt(e){e._o=mt,e._n=p,e._s=d,e._l=ut,e._t=lt,e._q=$,e._i=k,e._m=ht,e._f=ft,e._k=pt,e._b=vt,e._v=j,e._e=Yo,e._u=je,e._g=_t}function wt(e,t,n,r,i){var a,s=i.options;m(r,"_uid")?(a=Object.create(r),a._original=r):(a=r,r=r._original);var c=o(s._compiled),u=!c;this.data=e,this.props=t,this.children=n,this.parent=r,this.listeners=e.on||lo,this.injections=ct(s.inject,r),this.slots=function(){return Ie(n,r)},c&&(this.$options=s,this.$slots=this.slots(),this.$scopedSlots=e.scopedSlots||lo),s._scopeId?this._c=function(e,t,n,i){var o=Et(a,e,t,n,i,u);return o&&!Array.isArray(o)&&(o.fnScopeId=s._scopeId,o.fnContext=r),o}:this._c=function(e,t,n,r){return Et(a,e,t,n,r,u)}}function Ct(e,t,n,r,o){var a=e.options,s={},c=a.props;if(i(c))for(var u in c)s[u]=Q(u,c,t||lo);else i(n.attrs)&&$t(s,n.attrs),i(n.props)&&$t(s,n.props);var l=new wt(n,s,o,r,e),f=a.render.call(null,l._c,l);if(f instanceof Xo)return xt(f,n,l.parent,a,l);if(Array.isArray(f)){for(var d=ge(f)||[],p=new Array(d.length),v=0;v<d.length;v++)p[v]=xt(d[v],n,l.parent,a,l);return p}}function xt(e,t,n,r,i){var o=P(e);return o.fnContext=n,o.fnOptions=r,t.slot&&((o.data||(o.data={})).slot=t.slot),o}function $t(e,t){for(var n in t)e[yo(n)]=t[n]}function kt(e,t,n,a,s){if(!r(e)){var u=n.$options._base;if(c(e)&&(e=u.extend(e)),"function"==typeof e){var l;if(r(e.cid)&&(l=e,void 0===(e=xe(l,u,n))))return Ce(l,t,n,a,s);t=t||{},Nt(e),i(t.model)&&Ot(e.options,t);var f=he(t,e,s);if(o(e.options.functional))return Ct(e,f,t,n,a);var d=t.on;if(t.on=t.nativeOn,o(e.options.abstract)){var p=t.slot;t={},p&&(t.slot=p)}At(t);var v=e.options.name||s;return new Xo("vue-component-"+e.cid+(v?"-"+v:""),t,void 0,void 0,void 0,n,{Ctor:e,propsData:f,listeners:d,tag:s,children:a},l)}}}function St(e,t){var n={_isComponent:!0,_parentVnode:e,parent:t},r=e.data.inlineTemplate;return i(r)&&(n.render=r.render,n.staticRenderFns=r.staticRenderFns),new e.componentOptions.Ctor(n)}function At(e){for(var t=e.hook||(e.hook={}),n=0;n<Oa.length;n++){var r=Oa[n],i=t[r],o=Ta[r];i===o||i&&i._merged||(t[r]=i?Tt(o,i):o)}}function Tt(e,t){var n=function(n,r){e(n,r),t(n,r)};return n._merged=!0,n}function Ot(e,t){var n=e.model&&e.model.prop||"value",r=e.model&&e.model.event||"input";(t.props||(t.props={}))[n]=t.model.value;var o=t.on||(t.on={}),a=o[r],s=t.model.callback;i(a)?(Array.isArray(a)?-1===a.indexOf(s):a!==s)&&(o[r]=[s].concat(a)):o[r]=s}function Et(e,t,n,r,i,a){return(Array.isArray(n)||s(n))&&(i=r,r=n,n=void 0),o(a)&&(i=Ia),It(e,t,n,r,i)}function It(e,t,n,r,o){if(i(n)&&i(n.__ob__))return Yo();if(i(n)&&i(n.is)&&(t=n.is),!t)return Yo();Array.isArray(r)&&"function"==typeof r[0]&&(n=n||{},n.scopedSlots={default:r[0]},r.length=0),o===Ia?r=ge(r):o===Ea&&(r=ye(r));var a,s;if("string"==typeof t){var c;s=e.$vnode&&e.$vnode.ns||Ao.getTagNamespace(t),a=Ao.isReservedTag(t)?new Xo(Ao.parsePlatformTagName(t),n,r,void 0,void 0,e):n&&n.pre||!i(c=Y(e.$options,"components",t))?new Xo(t,n,r,void 0,void 0,e):kt(c,n,e,r,t)}else a=kt(t,n,e,r);return Array.isArray(a)?a:i(a)?(i(s)&&Lt(a,s),i(n)&&jt(n),a):Yo()}function Lt(e,t,n){if(e.ns=t,"foreignObject"===e.tag&&(t=void 0,n=!0),i(e.children))for(var a=0,s=e.children.length;a<s;a++){var c=e.children[a];i(c.tag)&&(r(c.ns)||o(n)&&"svg"!==c.tag)&&Lt(c,t,n)}}function jt(e){c(e.style)&&le(e.style),c(e.class)&&le(e.class)}function Pt(e){e._vnode=null,e._staticTrees=null;var t=e.$options,n=e.$vnode=t._parentVnode,r=n&&n.context;e.$slots=Ie(t._renderChildren,r),e.$scopedSlots=lo,e._c=function(t,n,r,i){return Et(e,t,n,r,i,!1)},e.$createElement=function(t,n,r,i){return Et(e,t,n,r,i,!0)};var i=n&&n.data;F(e,"$attrs",i&&i.attrs||lo,null,!0),F(e,"$listeners",t._parentListeners||lo,null,!0)}function Rt(e,t){var n=e.$options=Object.create(e.constructor.options),r=t._parentVnode;n.parent=t.parent,n._parentVnode=r;var i=r.componentOptions;n.propsData=i.propsData,n._parentListeners=i.listeners,n._renderChildren=i.children,n._componentTag=i.tag,t.render&&(n.render=t.render,n.staticRenderFns=t.staticRenderFns)}function Nt(e){var t=e.options;if(e.super){var n=Nt(e.super);if(n!==e.superOptions){e.superOptions=n;var r=Dt(e);r&&w(e.extendOptions,r),t=e.options=Z(n,e.extendOptions),t.name&&(t.components[t.name]=e)}}return t}function Dt(e){var t,n=e.options,r=e.sealedOptions;for(var i in n)n[i]!==r[i]&&(t||(t={}),t[i]=n[i]);return t}function Ut(e){this._init(e)}function Ft(e){e.use=function(e){var t=this._installedPlugins||(this._installedPlugins=[]);if(t.indexOf(e)>-1)return this;var n=b(arguments,1);return n.unshift(this),"function"==typeof e.install?e.install.apply(e,n):"function"==typeof e&&e.apply(null,n),t.push(e),this}}function Mt(e){e.mixin=function(e){return this.options=Z(this.options,e),this}}function Bt(e){e.cid=0;var t=1;e.extend=function(e){e=e||{};var n=this,r=n.cid,i=e._Ctor||(e._Ctor={});if(i[r])return i[r];var o=e.name||n.options.name,a=function(e){this._init(e)};return a.prototype=Object.create(n.prototype),a.prototype.constructor=a,a.cid=t++,a.options=Z(n.options,e),a.super=n,a.options.props&&Ht(a),a.options.computed&&zt(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,ko.forEach(function(e){a[e]=n[e]}),o&&(a.options.components[o]=a),a.superOptions=n.options,a.extendOptions=e,a.sealedOptions=w({},a.options),i[r]=a,a}}function Ht(e){var t=e.options.props;for(var n in t)Je(e.prototype,"_props",n)}function zt(e){var t=e.options.computed;for(var n in t)et(e.prototype,n,t[n])}function Vt(e){ko.forEach(function(t){e[t]=function(e,n){return n?("component"===t&&u(n)&&(n.name=n.name||e,n=this.options._base.extend(n)),"directive"===t&&"function"==typeof n&&(n={bind:n,update:n}),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}})}function qt(e){return e&&(e.Ctor.options.name||e.tag)}function Kt(e,t){return Array.isArray(e)?e.indexOf(t)>-1:"string"==typeof e?e.split(",").indexOf(t)>-1:!!l(e)&&e.test(t)}function Wt(e,t){var n=e.cache,r=e.keys,i=e._vnode;for(var o in n){var a=n[o];if(a){var s=qt(a.componentOptions);s&&!t(s)&&Jt(n,o,r,i)}}}function Jt(e,t,n,r){var i=e[t];!i||r&&i.tag===r.tag||i.componentInstance.$destroy(),e[t]=null,h(n,t)}function Gt(e){for(var t=e.data,n=e,r=e;i(r.componentInstance);)(r=r.componentInstance._vnode)&&r.data&&(t=Xt(r.data,t));for(;i(n=n.parent);)n&&n.data&&(t=Xt(t,n.data));return Zt(t.staticClass,t.class)}function Xt(e,t){return{staticClass:Yt(e.staticClass,t.staticClass),class:i(e.class)?[e.class,t.class]:t.class}}function Zt(e,t){return i(e)||i(t)?Yt(e,Qt(t)):""}function Yt(e,t){return e?t?e+" "+t:e:t||""}function Qt(e){return Array.isArray(e)?en(e):c(e)?tn(e):"string"==typeof e?e:""}function en(e){for(var t,n="",r=0,o=e.length;r<o;r++)i(t=Qt(e[r]))&&""!==t&&(n&&(n+=" "),n+=t);return n}function tn(e){var t="";for(var n in e)e[n]&&(t&&(t+=" "),t+=n);return t}function nn(e){return ns(e)?"svg":"math"===e?"math":void 0}function rn(e){if(!Eo)return!0;if(is(e))return!1;if(e=e.toLowerCase(),null!=os[e])return os[e];var t=document.createElement(e);return e.indexOf("-")>-1?os[e]=t.constructor===window.HTMLUnknownElement||t.constructor===window.HTMLElement:os[e]=/HTMLUnknownElement/.test(t.toString())}function on(e){if("string"==typeof e){return document.querySelector(e)||document.createElement("div")}return e}function an(e,t){var n=document.createElement(e);return"select"!==e?n:(t.data&&t.data.attrs&&void 0!==t.data.attrs.multiple&&n.setAttribute("multiple","multiple"),n)}function sn(e,t){return document.createElementNS(es[e],t)}function cn(e){return document.createTextNode(e)}function un(e){return document.createComment(e)}function ln(e,t,n){e.insertBefore(t,n)}function fn(e,t){e.removeChild(t)}function dn(e,t){e.appendChild(t)}function pn(e){return e.parentNode}function vn(e){return e.nextSibling}function hn(e){return e.tagName}function mn(e,t){e.textContent=t}function yn(e,t){e.setAttribute(t,"")}function gn(e,t){var n=e.data.ref;if(i(n)){var r=e.context,o=e.componentInstance||e.elm,a=r.$refs;t?Array.isArray(a[n])?h(a[n],o):a[n]===o&&(a[n]=void 0):e.data.refInFor?Array.isArray(a[n])?a[n].indexOf(o)<0&&a[n].push(o):a[n]=[o]:a[n]=o}}function _n(e,t){return e.key===t.key&&(e.tag===t.tag&&e.isComment===t.isComment&&i(e.data)===i(t.data)&&bn(e,t)||o(e.isAsyncPlaceholder)&&e.asyncFactory===t.asyncFactory&&r(t.asyncFactory.error))}function bn(e,t){if("input"!==e.tag)return!0;var n,r=i(n=e.data)&&i(n=n.attrs)&&n.type,o=i(n=t.data)&&i(n=n.attrs)&&n.type;return r===o||as(r)&&as(o)}function wn(e,t,n){var r,o,a={};for(r=t;r<=n;++r)o=e[r].key,i(o)&&(a[o]=r);return a}function Cn(e,t){(e.data.directives||t.data.directives)&&xn(e,t)}function xn(e,t){var n,r,i,o=e===us,a=t===us,s=$n(e.data.directives,e.context),c=$n(t.data.directives,t.context),u=[],l=[];for(n in c)r=s[n],i=c[n],r?(i.oldValue=r.value,Sn(i,"update",t,e),i.def&&i.def.componentUpdated&&l.push(i)):(Sn(i,"bind",t,e),i.def&&i.def.inserted&&u.push(i));if(u.length){var f=function(){for(var n=0;n<u.length;n++)Sn(u[n],"inserted",t,e)};o?ve(t,"insert",f):f()}if(l.length&&ve(t,"postpatch",function(){for(var n=0;n<l.length;n++)Sn(l[n],"componentUpdated",t,e)}),!o)for(n in s)c[n]||Sn(s[n],"unbind",e,e,a)}function $n(e,t){var n=Object.create(null);if(!e)return n;var r,i;for(r=0;r<e.length;r++)i=e[r],i.modifiers||(i.modifiers=ds),n[kn(i)]=i,i.def=Y(t.$options,"directives",i.name,!0);return n}function kn(e){return e.rawName||e.name+"."+Object.keys(e.modifiers||{}).join(".")}function Sn(e,t,n,r,i){var o=e.def&&e.def[t];if(o)try{o(n.elm,e,n,r,i)}catch(r){ie(r,n.context,"directive "+e.name+" "+t+" hook")}}function An(e,t){var n=t.componentOptions;if(!(i(n)&&!1===n.Ctor.options.inheritAttrs||r(e.data.attrs)&&r(t.data.attrs))){var o,a,s=t.elm,c=e.data.attrs||{},u=t.data.attrs||{};i(u.__ob__)&&(u=t.data.attrs=w({},u));for(o in u)a=u[o],c[o]!==a&&Tn(s,o,a);(Po||No)&&u.value!==c.value&&Tn(s,"value",u.value);for(o in c)r(u[o])&&(Za(o)?s.removeAttributeNS(Xa,Ya(o)):Ja(o)||s.removeAttribute(o))}}function Tn(e,t,n){e.tagName.indexOf("-")>-1?On(e,t,n):Ga(t)?Qa(n)?e.removeAttribute(t):(n="allowfullscreen"===t&&"EMBED"===e.tagName?"true":t,e.setAttribute(t,n)):Ja(t)?e.setAttribute(t,Qa(n)||"false"===n?"false":"true"):Za(t)?Qa(n)?e.removeAttributeNS(Xa,Ya(t)):e.setAttributeNS(Xa,t,n):On(e,t,n)}function On(e,t,n){if(Qa(n))e.removeAttribute(t);else{if(Po&&!Ro&&("TEXTAREA"===e.tagName||"INPUT"===e.tagName)&&"placeholder"===t&&!e.__ieph){var r=function(t){t.stopImmediatePropagation(),e.removeEventListener("input",r)};e.addEventListener("input",r),e.__ieph=!0}e.setAttribute(t,n)}}function En(e,t){var n=t.elm,o=t.data,a=e.data;if(!(r(o.staticClass)&&r(o.class)&&(r(a)||r(a.staticClass)&&r(a.class)))){var s=Gt(t),c=n._transitionClasses;i(c)&&(s=Yt(s,Qt(c))),s!==n._prevClass&&(n.setAttribute("class",s),n._prevClass=s)}}function In(e){function t(){(a||(a=[])).push(e.slice(v,i).trim()),v=i+1}var n,r,i,o,a,s=!1,c=!1,u=!1,l=!1,f=0,d=0,p=0,v=0;for(i=0;i<e.length;i++)if(r=n,n=e.charCodeAt(i),s)39===n&&92!==r&&(s=!1);else if(c)34===n&&92!==r&&(c=!1);else if(u)96===n&&92!==r&&(u=!1);else if(l)47===n&&92!==r&&(l=!1);else if(124!==n||124===e.charCodeAt(i+1)||124===e.charCodeAt(i-1)||f||d||p){switch(n){case 34:c=!0;break;case 39:s=!0;break;case 96:u=!0;break;case 40:p++;break;case 41:p--;break;case 91:d++;break;case 93:d--;break;case 123:f++;break;case 125:f--}if(47===n){for(var h=i-1,m=void 0;h>=0&&" "===(m=e.charAt(h));h--);m&&ms.test(m)||(l=!0)}}else void 0===o?(v=i+1,o=e.slice(0,i).trim()):t();if(void 0===o?o=e.slice(0,i).trim():0!==v&&t(),a)for(i=0;i<a.length;i++)o=Ln(o,a[i]);return o}function Ln(e,t){var n=t.indexOf("(");if(n<0)return'_f("'+t+'")('+e+")";var r=t.slice(0,n),i=t.slice(n+1);return'_f("'+r+'")('+e+(")"!==i?","+i:i)}function jn(e){console.error("[Vue compiler]: "+e)}function Pn(e,t){return e?e.map(function(e){return e[t]}).filter(function(e){return e}):[]}function Rn(e,t,n){(e.props||(e.props=[])).push({name:t,value:n}),e.plain=!1}function Nn(e,t,n){(e.attrs||(e.attrs=[])).push({name:t,value:n}),e.plain=!1}function Dn(e,t,n){e.attrsMap[t]=n,e.attrsList.push({name:t,value:n})}function Un(e,t,n,r,i,o){(e.directives||(e.directives=[])).push({name:t,rawName:n,value:r,arg:i,modifiers:o}),e.plain=!1}function Fn(e,t,n,r,i,o){r=r||lo,"click"===t&&(r.right?(t="contextmenu",delete r.right):r.middle&&(t="mouseup")),r.capture&&(delete r.capture,t="!"+t),r.once&&(delete r.once,t="~"+t),r.passive&&(delete r.passive,t="&"+t);var a;r.native?(delete r.native,a=e.nativeEvents||(e.nativeEvents={})):a=e.events||(e.events={});var s={value:n.trim()};r!==lo&&(s.modifiers=r);var c=a[t];Array.isArray(c)?i?c.unshift(s):c.push(s):a[t]=c?i?[s,c]:[c,s]:s,e.plain=!1}function Mn(e,t,n){var r=Bn(e,":"+t)||Bn(e,"v-bind:"+t);if(null!=r)return In(r);if(!1!==n){var i=Bn(e,t);if(null!=i)return JSON.stringify(i)}}function Bn(e,t,n){var r;if(null!=(r=e.attrsMap[t]))for(var i=e.attrsList,o=0,a=i.length;o<a;o++)if(i[o].name===t){i.splice(o,1);break}return n&&delete e.attrsMap[t],r}function Hn(e,t,n){var r=n||{},i=r.number,o=r.trim,a="$$v";o&&(a="(typeof $$v === 'string'? $$v.trim(): $$v)"),i&&(a="_n("+a+")");var s=zn(t,a);e.model={value:"("+t+")",expression:JSON.stringify(t),callback:"function ($$v) {"+s+"}"}}function zn(e,t){var n=Vn(e);return null===n.key?e+"="+t:"$set("+n.exp+", "+n.key+", "+t+")"}function Vn(e){if(e=e.trim(),Na=e.length,e.indexOf("[")<0||e.lastIndexOf("]")<Na-1)return Fa=e.lastIndexOf("."),Fa>-1?{exp:e.slice(0,Fa),key:'"'+e.slice(Fa+1)+'"'}:{exp:e,key:null};for(Da=e,Fa=Ma=Ba=0;!Kn();)Ua=qn(),Wn(Ua)?Gn(Ua):91===Ua&&Jn(Ua);return{exp:e.slice(0,Ma),key:e.slice(Ma+1,Ba)}}function qn(){return Da.charCodeAt(++Fa)}function Kn(){return Fa>=Na}function Wn(e){return 34===e||39===e}function Jn(e){var t=1;for(Ma=Fa;!Kn();)if(e=qn(),Wn(e))Gn(e);else if(91===e&&t++,93===e&&t--,0===t){Ba=Fa;break}}function Gn(e){for(var t=e;!Kn()&&(e=qn())!==t;);}function Xn(e,t,n){Ha=n;var r=t.value,i=t.modifiers,o=e.tag,a=e.attrsMap.type;if(e.component)return Hn(e,r,i),!1;if("select"===o)Qn(e,r,i);else if("input"===o&&"checkbox"===a)Zn(e,r,i);else if("input"===o&&"radio"===a)Yn(e,r,i);else if("input"===o||"textarea"===o)er(e,r,i);else if(!Ao.isReservedTag(o))return Hn(e,r,i),!1;return!0}function Zn(e,t,n){var r=n&&n.number,i=Mn(e,"value")||"null",o=Mn(e,"true-value")||"true",a=Mn(e,"false-value")||"false";Rn(e,"checked","Array.isArray("+t+")?_i("+t+","+i+")>-1"+("true"===o?":("+t+")":":_q("+t+","+o+")")),Fn(e,"change","var $$a="+t+",$$el=$event.target,$$c=$$el.checked?("+o+"):("+a+");if(Array.isArray($$a)){var $$v="+(r?"_n("+i+")":i)+",$$i=_i($$a,$$v);if($$el.checked){$$i<0&&("+zn(t,"$$a.concat([$$v])")+")}else{$$i>-1&&("+zn(t,"$$a.slice(0,$$i).concat($$a.slice($$i+1))")+")}}else{"+zn(t,"$$c")+"}",null,!0)}function Yn(e,t,n){var r=n&&n.number,i=Mn(e,"value")||"null";i=r?"_n("+i+")":i,Rn(e,"checked","_q("+t+","+i+")"),Fn(e,"change",zn(t,i),null,!0)}function Qn(e,t,n){var r=n&&n.number,i='Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = "_value" in o ? o._value : o.value;return '+(r?"_n(val)":"val")+"})",o="var $$selectedVal = "+i+";";o=o+" "+zn(t,"$event.target.multiple ? $$selectedVal : $$selectedVal[0]"),Fn(e,"change",o,null,!0)}function er(e,t,n){var r=e.attrsMap.type,i=n||{},o=i.lazy,a=i.number,s=i.trim,c=!o&&"range"!==r,u=o?"change":"range"===r?ys:"input",l="$event.target.value";s&&(l="$event.target.value.trim()"),a&&(l="_n("+l+")");var f=zn(t,l);c&&(f="if($event.target.composing)return;"+f),Rn(e,"value","("+t+")"),Fn(e,u,f,null,!0),(s||a)&&Fn(e,"blur","$forceUpdate()")}function tr(e){if(i(e[ys])){var t=Po?"change":"input";e[t]=[].concat(e[ys],e[t]||[]),delete e[ys]}i(e[gs])&&(e.change=[].concat(e[gs],e.change||[]),delete e[gs])}function nr(e,t,n){var r=za;return function i(){null!==t.apply(null,arguments)&&ir(e,i,n,r)}}function rr(e,t,n,r){t=ce(t),za.addEventListener(e,t,Fo?{capture:n,passive:r}:n)}function ir(e,t,n,r){(r||za).removeEventListener(e,t._withTask||t,n)}function or(e,t){if(!r(e.data.on)||!r(t.data.on)){var n=t.data.on||{},i=e.data.on||{};za=t.elm,tr(n),pe(n,i,rr,ir,nr,t.context),za=void 0}}function ar(e,t){if(!r(e.data.domProps)||!r(t.data.domProps)){var n,o,a=t.elm,s=e.data.domProps||{},c=t.data.domProps||{};i(c.__ob__)&&(c=t.data.domProps=w({},c));for(n in s)r(c[n])&&(a[n]="");for(n in c){if(o=c[n],"textContent"===n||"innerHTML"===n){if(t.children&&(t.children.length=0),o===s[n])continue;1===a.childNodes.length&&a.removeChild(a.childNodes[0])}if("value"===n){a._value=o;var u=r(o)?"":String(o);sr(a,u)&&(a.value=u)}else a[n]=o}}}function sr(e,t){return!e.composing&&("OPTION"===e.tagName||cr(e,t)||ur(e,t))}function cr(e,t){var n=!0;try{n=document.activeElement!==e}catch(e){}return n&&e.value!==t}function ur(e,t){var n=e.value,r=e._vModifiers;if(i(r)){if(r.lazy)return!1;if(r.number)return p(n)!==p(t);if(r.trim)return n.trim()!==t.trim()}return n!==t}function lr(e){var t=fr(e.style);return e.staticStyle?w(e.staticStyle,t):t}function fr(e){return Array.isArray(e)?C(e):"string"==typeof e?ws(e):e}function dr(e,t){var n,r={};if(t)for(var i=e;i.componentInstance;)(i=i.componentInstance._vnode)&&i.data&&(n=lr(i.data))&&w(r,n);(n=lr(e.data))&&w(r,n);for(var o=e;o=o.parent;)o.data&&(n=lr(o.data))&&w(r,n);return r}function pr(e,t){var n=t.data,o=e.data;if(!(r(n.staticStyle)&&r(n.style)&&r(o.staticStyle)&&r(o.style))){var a,s,c=t.elm,u=o.staticStyle,l=o.normalizedStyle||o.style||{},f=u||l,d=fr(t.data.style)||{};t.data.normalizedStyle=i(d.__ob__)?w({},d):d;var p=dr(t,!0);for(s in f)r(p[s])&&$s(c,s,"");for(s in p)(a=p[s])!==f[s]&&$s(c,s,null==a?"":a)}}function vr(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(Ts).forEach(function(t){return e.classList.add(t)}):e.classList.add(t);else{var n=" "+(e.getAttribute("class")||"")+" ";n.indexOf(" "+t+" ")<0&&e.setAttribute("class",(n+t).trim())}}function hr(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(Ts).forEach(function(t){return e.classList.remove(t)}):e.classList.remove(t),e.classList.length||e.removeAttribute("class");else{for(var n=" "+(e.getAttribute("class")||"")+" ",r=" "+t+" ";n.indexOf(r)>=0;)n=n.replace(r," ");n=n.trim(),n?e.setAttribute("class",n):e.removeAttribute("class")}}function mr(e){if(e){if("object"==typeof e){var t={};return!1!==e.css&&w(t,Os(e.name||"v")),w(t,e),t}return"string"==typeof e?Os(e):void 0}}function yr(e){Ds(function(){Ds(e)})}function gr(e,t){var n=e._transitionClasses||(e._transitionClasses=[]);n.indexOf(t)<0&&(n.push(t),vr(e,t))}function _r(e,t){e._transitionClasses&&h(e._transitionClasses,t),hr(e,t)}function br(e,t,n){var r=wr(e,t),i=r.type,o=r.timeout,a=r.propCount;if(!i)return n();var s=i===Is?Ps:Ns,c=0,u=function(){e.removeEventListener(s,l),n()},l=function(t){t.target===e&&++c>=a&&u()};setTimeout(function(){c<a&&u()},o+1),e.addEventListener(s,l)}function wr(e,t){var n,r=window.getComputedStyle(e),i=(r[js+"Delay"]||"").split(", "),o=(r[js+"Duration"]||"").split(", "),a=Cr(i,o),s=(r[Rs+"Delay"]||"").split(", "),c=(r[Rs+"Duration"]||"").split(", "),u=Cr(s,c),l=0,f=0;return t===Is?a>0&&(n=Is,l=a,f=o.length):t===Ls?u>0&&(n=Ls,l=u,f=c.length):(l=Math.max(a,u),n=l>0?a>u?Is:Ls:null,f=n?n===Is?o.length:c.length:0),{type:n,timeout:l,propCount:f,hasTransform:n===Is&&Us.test(r[js+"Property"])}}function Cr(e,t){for(;e.length<t.length;)e=e.concat(e);return Math.max.apply(null,t.map(function(t,n){return xr(t)+xr(e[n])}))}function xr(e){return 1e3*Number(e.slice(0,-1).replace(",","."))}function $r(e,t){var n=e.elm;i(n._leaveCb)&&(n._leaveCb.cancelled=!0,n._leaveCb());var o=mr(e.data.transition);if(!r(o)&&!i(n._enterCb)&&1===n.nodeType){for(var a=o.css,s=o.type,u=o.enterClass,l=o.enterToClass,f=o.enterActiveClass,d=o.appearClass,v=o.appearToClass,h=o.appearActiveClass,m=o.beforeEnter,y=o.enter,g=o.afterEnter,_=o.enterCancelled,b=o.beforeAppear,w=o.appear,C=o.afterAppear,x=o.appearCancelled,$=o.duration,k=ya,A=ya.$vnode;A&&A.parent;)A=A.parent,k=A.context;var T=!k._isMounted||!e.isRootInsert;if(!T||w||""===w){var O=T&&d?d:u,E=T&&h?h:f,I=T&&v?v:l,L=T?b||m:m,j=T&&"function"==typeof w?w:y,P=T?C||g:g,R=T?x||_:_,N=p(c($)?$.enter:$),D=!1!==a&&!Ro,U=Ar(j),F=n._enterCb=S(function(){D&&(_r(n,I),_r(n,E)),F.cancelled?(D&&_r(n,O),R&&R(n)):P&&P(n),n._enterCb=null});e.data.show||ve(e,"insert",function(){var t=n.parentNode,r=t&&t._pending&&t._pending[e.key];r&&r.tag===e.tag&&r.elm._leaveCb&&r.elm._leaveCb(),j&&j(n,F)}),L&&L(n),D&&(gr(n,O),gr(n,E),yr(function(){_r(n,O),F.cancelled||(gr(n,I),U||(Sr(N)?setTimeout(F,N):br(n,s,F)))})),e.data.show&&(t&&t(),j&&j(n,F)),D||U||F()}}}function kr(e,t){function n(){x.cancelled||(!e.data.show&&o.parentNode&&((o.parentNode._pending||(o.parentNode._pending={}))[e.key]=e),v&&v(o),b&&(gr(o,l),gr(o,d),yr(function(){_r(o,l),x.cancelled||(gr(o,f),w||(Sr(C)?setTimeout(x,C):br(o,u,x)))})),h&&h(o,x),b||w||x())}var o=e.elm;i(o._enterCb)&&(o._enterCb.cancelled=!0,o._enterCb());var a=mr(e.data.transition);if(r(a)||1!==o.nodeType)return t();if(!i(o._leaveCb)){var s=a.css,u=a.type,l=a.leaveClass,f=a.leaveToClass,d=a.leaveActiveClass,v=a.beforeLeave,h=a.leave,m=a.afterLeave,y=a.leaveCancelled,g=a.delayLeave,_=a.duration,b=!1!==s&&!Ro,w=Ar(h),C=p(c(_)?_.leave:_),x=o._leaveCb=S(function(){o.parentNode&&o.parentNode._pending&&(o.parentNode._pending[e.key]=null),b&&(_r(o,f),_r(o,d)),x.cancelled?(b&&_r(o,l),y&&y(o)):(t(),m&&m(o)),o._leaveCb=null});g?g(n):n()}}function Sr(e){return"number"==typeof e&&!isNaN(e)}function Ar(e){if(r(e))return!1;var t=e.fns;return i(t)?Ar(Array.isArray(t)?t[0]:t):(e._length||e.length)>1}function Tr(e,t){!0!==t.data.show&&$r(t)}function Or(e,t,n){Er(e,t,n),(Po||No)&&setTimeout(function(){Er(e,t,n)},0)}function Er(e,t,n){var r=t.value,i=e.multiple;if(!i||Array.isArray(r)){for(var o,a,s=0,c=e.options.length;s<c;s++)if(a=e.options[s],i)o=k(r,Lr(a))>-1,a.selected!==o&&(a.selected=o);else if($(Lr(a),r))return void(e.selectedIndex!==s&&(e.selectedIndex=s));i||(e.selectedIndex=-1)}}function Ir(e,t){return t.every(function(t){return!$(t,e)})}function Lr(e){return"_value"in e?e._value:e.value}function jr(e){e.target.composing=!0}function Pr(e){e.target.composing&&(e.target.composing=!1,Rr(e.target,"input"))}function Rr(e,t){var n=document.createEvent("HTMLEvents");n.initEvent(t,!0,!0),e.dispatchEvent(n)}function Nr(e){return!e.componentInstance||e.data&&e.data.transition?e:Nr(e.componentInstance._vnode)}function Dr(e){var t=e&&e.componentOptions;return t&&t.Ctor.options.abstract?Dr(ke(t.children)):e}function Ur(e){var t={},n=e.$options;for(var r in n.propsData)t[r]=e[r];var i=n._parentListeners;for(var o in i)t[yo(o)]=i[o];return t}function Fr(e,t){if(/\d-keep-alive$/.test(t.tag))return e("keep-alive",{props:t.componentOptions.propsData})}function Mr(e){for(;e=e.parent;)if(e.data.transition)return!0}function Br(e,t){return t.key===e.key&&t.tag===e.tag}function Hr(e){e.elm._moveCb&&e.elm._moveCb(),e.elm._enterCb&&e.elm._enterCb()}function zr(e){e.data.newPos=e.elm.getBoundingClientRect()}function Vr(e){var t=e.data.pos,n=e.data.newPos,r=t.left-n.left,i=t.top-n.top;if(r||i){e.data.moved=!0;var o=e.elm.style;o.transform=o.WebkitTransform="translate("+r+"px,"+i+"px)",o.transitionDuration="0s"}}function qr(e,t){var n=t?pc(t):fc;if(n.test(e)){for(var r,i,o,a=[],s=[],c=n.lastIndex=0;r=n.exec(e);){(i=r.index)>c&&(s.push(o=e.slice(c,i)),a.push(JSON.stringify(o)));var u=In(r[1].trim());a.push("_s("+u+")"),s.push({"@binding":u}),c=i+r[0].length}return c<e.length&&(s.push(o=e.slice(c)),a.push(JSON.stringify(o))),{expression:a.join("+"),tokens:s}}}function Kr(e,t){var n=(t.warn,Bn(e,"class"));n&&(e.staticClass=JSON.stringify(n));var r=Mn(e,"class",!1);r&&(e.classBinding=r)}function Wr(e){var t="";return e.staticClass&&(t+="staticClass:"+e.staticClass+","),e.classBinding&&(t+="class:"+e.classBinding+","),t}function Jr(e,t){var n=(t.warn,Bn(e,"style"));n&&(e.staticStyle=JSON.stringify(ws(n)));var r=Mn(e,"style",!1);r&&(e.styleBinding=r)}function Gr(e){var t="";return e.staticStyle&&(t+="staticStyle:"+e.staticStyle+","),e.styleBinding&&(t+="style:("+e.styleBinding+"),"),t}function Xr(e,t){var n=t?jc:Lc;return e.replace(n,function(e){return Ic[e]})}function Zr(e,t){function n(t){l+=t,e=e.substring(t)}function r(e,n,r){var i,s;if(null==n&&(n=l),null==r&&(r=l),e)for(s=e.toLowerCase(),i=a.length-1;i>=0&&a[i].lowerCasedTag!==s;i--);else i=0;if(i>=0){for(var c=a.length-1;c>=i;c--)t.end&&t.end(a[c].tag,n,r);a.length=i,o=i&&a[i-1].tag}else"br"===s?t.start&&t.start(e,[],!0,n,r):"p"===s&&(t.start&&t.start(e,[],!1,n,r),t.end&&t.end(e,n,r))}for(var i,o,a=[],s=t.expectHTML,c=t.isUnaryTag||Co,u=t.canBeLeftOpenTag||Co,l=0;e;){if(i=e,o&&Oc(o)){var f=0,d=o.toLowerCase(),p=Ec[d]||(Ec[d]=new RegExp("([\\s\\S]*?)(</"+d+"[^>]*>)","i")),v=e.replace(p,function(e,n,r){return f=r.length,Oc(d)||"noscript"===d||(n=n.replace(/<!\--([\s\S]*?)-->/g,"$1").replace(/<!\[CDATA\[([\s\S]*?)]]>/g,"$1")),Rc(d,n)&&(n=n.slice(1)),t.chars&&t.chars(n),""});l+=e.length-v.length,e=v,r(d,l-f,l)}else{var h=e.indexOf("<");if(0===h){if(Ac.test(e)){var m=e.indexOf("--\x3e");if(m>=0){t.shouldKeepComment&&t.comment(e.substring(4,m)),n(m+3);continue}}if(Tc.test(e)){var y=e.indexOf("]>");if(y>=0){n(y+2);continue}}var g=e.match(Sc);if(g){n(g[0].length);continue}var _=e.match(kc);if(_){var b=l;n(_[0].length),r(_[1],b,l);continue}var w=function(){var t=e.match(xc);if(t){var r={tagName:t[1],attrs:[],start:l};n(t[0].length);for(var i,o;!(i=e.match($c))&&(o=e.match(bc));)n(o[0].length),r.attrs.push(o);if(i)return r.unarySlash=i[1],n(i[0].length),r.end=l,r}}();if(w){!function(e){var n=e.tagName,i=e.unarySlash;s&&("p"===o&&_c(n)&&r(o),u(n)&&o===n&&r(n));for(var l=c(n)||!!i,f=e.attrs.length,d=new Array(f),p=0;p<f;p++){var v=e.attrs[p],h=v[3]||v[4]||v[5]||"",m="a"===n&&"href"===v[1]?t.shouldDecodeNewlinesForHref:t.shouldDecodeNewlines;d[p]={name:v[1],value:Xr(h,m)}}l||(a.push({tag:n,lowerCasedTag:n.toLowerCase(),attrs:d}),o=n),t.start&&t.start(n,d,l,e.start,e.end)}(w),Rc(w.tagName,e)&&n(1);continue}}var C=void 0,x=void 0,$=void 0;if(h>=0){for(x=e.slice(h);!(kc.test(x)||xc.test(x)||Ac.test(x)||Tc.test(x)||($=x.indexOf("<",1))<0);)h+=$,x=e.slice(h);C=e.substring(0,h),n(h)}h<0&&(C=e,e=""),t.chars&&C&&t.chars(C)}if(e===i){t.chars&&t.chars(e);break}}r()}function Yr(e,t,n){return{type:1,tag:e,attrsList:t,attrsMap:yi(t),parent:n,children:[]}}function Qr(e,t){function n(e){e.pre&&(s=!1),oc(e.tag)&&(c=!1);for(var n=0;n<ic.length;n++)ic[n](e,t)}ec=t.warn||jn,oc=t.isPreTag||Co,ac=t.mustUseProp||Co,sc=t.getTagNamespace||Co,nc=Pn(t.modules,"transformNode"),rc=Pn(t.modules,"preTransformNode"),ic=Pn(t.modules,"postTransformNode"),tc=t.delimiters;var r,i,o=[],a=!1!==t.preserveWhitespace,s=!1,c=!1;return Zr(e,{warn:ec,expectHTML:t.expectHTML,isUnaryTag:t.isUnaryTag,canBeLeftOpenTag:t.canBeLeftOpenTag,shouldDecodeNewlines:t.shouldDecodeNewlines,shouldDecodeNewlinesForHref:t.shouldDecodeNewlinesForHref,shouldKeepComment:t.comments,start:function(e,a,u){var l=i&&i.ns||sc(e);Po&&"svg"===l&&(a=bi(a));var f=Yr(e,a,i);l&&(f.ns=l),_i(f)&&!zo()&&(f.forbidden=!0);for(var d=0;d<rc.length;d++)f=rc[d](f,t)||f;if(s||(ei(f),f.pre&&(s=!0)),oc(f.tag)&&(c=!0),s?ti(f):f.processed||(oi(f),si(f),fi(f),ni(f,t)),r?o.length||r.if&&(f.elseif||f.else)&&li(r,{exp:f.elseif,block:f}):r=f,i&&!f.forbidden)if(f.elseif||f.else)ci(f,i);else if(f.slotScope){i.plain=!1;var p=f.slotTarget||'"default"';(i.scopedSlots||(i.scopedSlots={}))[p]=f}else i.children.push(f),f.parent=i;u?n(f):(i=f,o.push(f))},end:function(){var e=o[o.length-1],t=e.children[e.children.length-1];t&&3===t.type&&" "===t.text&&!c&&e.children.pop(),o.length-=1,i=o[o.length-1],n(e)},chars:function(e){if(i&&(!Po||"textarea"!==i.tag||i.attrsMap.placeholder!==e)){var t=i.children;if(e=c||e.trim()?gi(i)?e:Vc(e):a&&t.length?" ":""){var n;!s&&" "!==e&&(n=qr(e,tc))?t.push({type:2,expression:n.expression,tokens:n.tokens,text:e}):" "===e&&t.length&&" "===t[t.length-1].text||t.push({type:3,text:e})}}},comment:function(e){i.children.push({type:3,text:e,isComment:!0})}}),r}function ei(e){null!=Bn(e,"v-pre")&&(e.pre=!0)}function ti(e){var t=e.attrsList.length;if(t)for(var n=e.attrs=new Array(t),r=0;r<t;r++)n[r]={name:e.attrsList[r].name,value:JSON.stringify(e.attrsList[r].value)};else e.pre||(e.plain=!0)}function ni(e,t){ri(e),e.plain=!e.key&&!e.attrsList.length,ii(e),di(e),pi(e);for(var n=0;n<nc.length;n++)e=nc[n](e,t)||e;vi(e)}function ri(e){var t=Mn(e,"key");t&&(e.key=t)}function ii(e){var t=Mn(e,"ref");t&&(e.ref=t,e.refInFor=hi(e))}function oi(e){var t;if(t=Bn(e,"v-for")){var n=ai(t);n&&w(e,n)}}function ai(e){var t=e.match(Uc);if(t){var n={};n.for=t[2].trim();var r=t[1].trim().replace(Mc,""),i=r.match(Fc);return i?(n.alias=r.replace(Fc,"").trim(),n.iterator1=i[1].trim(),i[2]&&(n.iterator2=i[2].trim())):n.alias=r,n}}function si(e){var t=Bn(e,"v-if");if(t)e.if=t,li(e,{exp:t,block:e});else{null!=Bn(e,"v-else")&&(e.else=!0);var n=Bn(e,"v-else-if");n&&(e.elseif=n)}}function ci(e,t){var n=ui(t.children);n&&n.if&&li(n,{exp:e.elseif,block:e})}function ui(e){for(var t=e.length;t--;){if(1===e[t].type)return e[t];e.pop()}}function li(e,t){e.ifConditions||(e.ifConditions=[]),e.ifConditions.push(t)}function fi(e){null!=Bn(e,"v-once")&&(e.once=!0)}function di(e){if("slot"===e.tag)e.slotName=Mn(e,"name");else{var t;"template"===e.tag?(t=Bn(e,"scope"),e.slotScope=t||Bn(e,"slot-scope")):(t=Bn(e,"slot-scope"))&&(e.slotScope=t);var n=Mn(e,"slot");n&&(e.slotTarget='""'===n?'"default"':n,"template"===e.tag||e.slotScope||Nn(e,"slot",n))}}function pi(e){var t;(t=Mn(e,"is"))&&(e.component=t),null!=Bn(e,"inline-template")&&(e.inlineTemplate=!0)}function vi(e){var t,n,r,i,o,a,s,c=e.attrsList;for(t=0,n=c.length;t<n;t++)if(r=i=c[t].name,o=c[t].value,Dc.test(r))if(e.hasBindings=!0,a=mi(r),a&&(r=r.replace(zc,"")),Hc.test(r))r=r.replace(Hc,""),o=In(o),s=!1,a&&(a.prop&&(s=!0,"innerHtml"===(r=yo(r))&&(r="innerHTML")),a.camel&&(r=yo(r)),a.sync&&Fn(e,"update:"+yo(r),zn(o,"$event"))),s||!e.component&&ac(e.tag,e.attrsMap.type,r)?Rn(e,r,o):Nn(e,r,o);else if(Nc.test(r))r=r.replace(Nc,""),Fn(e,r,o,a,!1,ec);else{r=r.replace(Dc,"");var u=r.match(Bc),l=u&&u[1];l&&(r=r.slice(0,-(l.length+1))),Un(e,r,i,o,l,a)}else Nn(e,r,JSON.stringify(o)),!e.component&&"muted"===r&&ac(e.tag,e.attrsMap.type,r)&&Rn(e,r,"true")}function hi(e){for(var t=e;t;){if(void 0!==t.for)return!0;t=t.parent}return!1}function mi(e){var t=e.match(zc);if(t){var n={};return t.forEach(function(e){n[e.slice(1)]=!0}),n}}function yi(e){for(var t={},n=0,r=e.length;n<r;n++)t[e[n].name]=e[n].value;return t}function gi(e){return"script"===e.tag||"style"===e.tag}function _i(e){return"style"===e.tag||"script"===e.tag&&(!e.attrsMap.type||"text/javascript"===e.attrsMap.type)}function bi(e){for(var t=[],n=0;n<e.length;n++){var r=e[n];qc.test(r.name)||(r.name=r.name.replace(Kc,""),t.push(r))}return t}function wi(e,t){if("input"===e.tag){var n=e.attrsMap;if(!n["v-model"])return;var r;if((n[":type"]||n["v-bind:type"])&&(r=Mn(e,"type")),n.type||r||!n["v-bind"]||(r="("+n["v-bind"]+").type"),r){var i=Bn(e,"v-if",!0),o=i?"&&("+i+")":"",a=null!=Bn(e,"v-else",!0),s=Bn(e,"v-else-if",!0),c=Ci(e);oi(c),Dn(c,"type","checkbox"),ni(c,t),c.processed=!0,c.if="("+r+")==='checkbox'"+o,li(c,{exp:c.if,block:c});var u=Ci(e);Bn(u,"v-for",!0),Dn(u,"type","radio"),ni(u,t),li(c,{exp:"("+r+")==='radio'"+o,block:u});var l=Ci(e);return Bn(l,"v-for",!0),Dn(l,":type",r),ni(l,t),li(c,{exp:i,block:l}),a?c.else=!0:s&&(c.elseif=s),c}}}function Ci(e){return Yr(e.tag,e.attrsList.slice(),e.parent)}function xi(e,t){t.value&&Rn(e,"textContent","_s("+t.value+")")}function $i(e,t){t.value&&Rn(e,"innerHTML","_s("+t.value+")")}function ki(e,t){e&&(cc=Zc(t.staticKeys||""),uc=t.isReservedTag||Co,Ai(e),Ti(e,!1))}function Si(e){return v("type,tag,attrsList,attrsMap,plain,parent,children,attrs"+(e?","+e:""))}function Ai(e){if(e.static=Oi(e),1===e.type){if(!uc(e.tag)&&"slot"!==e.tag&&null==e.attrsMap["inline-template"])return;for(var t=0,n=e.children.length;t<n;t++){var r=e.children[t];Ai(r),r.static||(e.static=!1)}if(e.ifConditions)for(var i=1,o=e.ifConditions.length;i<o;i++){var a=e.ifConditions[i].block;Ai(a),a.static||(e.static=!1)}}}function Ti(e,t){if(1===e.type){if((e.static||e.once)&&(e.staticInFor=t),e.static&&e.children.length&&(1!==e.children.length||3!==e.children[0].type))return void(e.staticRoot=!0);if(e.staticRoot=!1,e.children)for(var n=0,r=e.children.length;n<r;n++)Ti(e.children[n],t||!!e.for);if(e.ifConditions)for(var i=1,o=e.ifConditions.length;i<o;i++)Ti(e.ifConditions[i].block,t)}}function Oi(e){return 2!==e.type&&(3===e.type||!(!e.pre&&(e.hasBindings||e.if||e.for||po(e.tag)||!uc(e.tag)||Ei(e)||!Object.keys(e).every(cc))))}function Ei(e){for(;e.parent;){if(e=e.parent,"template"!==e.tag)return!1;if(e.for)return!0}return!1}function Ii(e,t){var n=t?"nativeOn:{":"on:{";for(var r in e)n+='"'+r+'":'+Li(r,e[r])+",";return n.slice(0,-1)+"}"}function Li(e,t){if(!t)return"function(){}";if(Array.isArray(t))return"["+t.map(function(t){return Li(e,t)}).join(",")+"]";var n=Qc.test(t.value),r=Yc.test(t.value);if(t.modifiers){var i="",o="",a=[];for(var s in t.modifiers)if(ru[s])o+=ru[s],eu[s]&&a.push(s);else if("exact"===s){var c=t.modifiers;o+=nu(["ctrl","shift","alt","meta"].filter(function(e){return!c[e]}).map(function(e){return"$event."+e+"Key"}).join("||"))}else a.push(s);return a.length&&(i+=ji(a)),o&&(i+=o),"function($event){"+i+(n?"return "+t.value+"($event)":r?"return ("+t.value+")($event)":t.value)+"}"}return n||r?t.value:"function($event){"+t.value+"}"}function ji(e){return"if(!('button' in $event)&&"+e.map(Pi).join("&&")+")return null;"}function Pi(e){var t=parseInt(e,10);if(t)return"$event.keyCode!=="+t;var n=eu[e],r=tu[e];return"_k($event.keyCode,"+JSON.stringify(e)+","+JSON.stringify(n)+",$event.key,"+JSON.stringify(r)+")"}function Ri(e,t){e.wrapListeners=function(e){return"_g("+e+","+t.value+")"}}function Ni(e,t){e.wrapData=function(n){return"_b("+n+",'"+e.tag+"',"+t.value+","+(t.modifiers&&t.modifiers.prop?"true":"false")+(t.modifiers&&t.modifiers.sync?",true":"")+")"}}function Di(e,t){var n=new ou(t);return{render:"with(this){return "+(e?Ui(e,n):'_c("div")')+"}",staticRenderFns:n.staticRenderFns}}function Ui(e,t){if(e.parent&&(e.pre=e.pre||e.parent.pre),e.staticRoot&&!e.staticProcessed)return Fi(e,t);if(e.once&&!e.onceProcessed)return Mi(e,t);if(e.for&&!e.forProcessed)return zi(e,t);if(e.if&&!e.ifProcessed)return Bi(e,t);if("template"!==e.tag||e.slotTarget||t.pre){if("slot"===e.tag)return no(e,t);var n;if(e.component)n=ro(e.component,e,t);else{var r;(!e.plain||e.pre&&t.maybeComponent(e))&&(r=Vi(e,t));var i=e.inlineTemplate?null:Xi(e,t,!0);n="_c('"+e.tag+"'"+(r?","+r:"")+(i?","+i:"")+")"}for(var o=0;o<t.transforms.length;o++)n=t.transforms[o](e,n);return n}return Xi(e,t)||"void 0"}function Fi(e,t){e.staticProcessed=!0;var n=t.pre;return e.pre&&(t.pre=e.pre),t.staticRenderFns.push("with(this){return "+Ui(e,t)+"}"),t.pre=n,"_m("+(t.staticRenderFns.length-1)+(e.staticInFor?",true":"")+")"}function Mi(e,t){if(e.onceProcessed=!0,e.if&&!e.ifProcessed)return Bi(e,t);if(e.staticInFor){for(var n="",r=e.parent;r;){if(r.for){n=r.key;break}r=r.parent}return n?"_o("+Ui(e,t)+","+t.onceId+++","+n+")":Ui(e,t)}return Fi(e,t)}function Bi(e,t,n,r){return e.ifProcessed=!0,Hi(e.ifConditions.slice(),t,n,r)}function Hi(e,t,n,r){function i(e){return n?n(e,t):e.once?Mi(e,t):Ui(e,t)}if(!e.length)return r||"_e()";var o=e.shift();return o.exp?"("+o.exp+")?"+i(o.block)+":"+Hi(e,t,n,r):""+i(o.block)}function zi(e,t,n,r){var i=e.for,o=e.alias,a=e.iterator1?","+e.iterator1:"",s=e.iterator2?","+e.iterator2:"";return e.forProcessed=!0,(r||"_l")+"(("+i+"),function("+o+a+s+"){return "+(n||Ui)(e,t)+"})"}function Vi(e,t){var n="{",r=qi(e,t);r&&(n+=r+","),e.key&&(n+="key:"+e.key+","),e.ref&&(n+="ref:"+e.ref+","),e.refInFor&&(n+="refInFor:true,"),e.pre&&(n+="pre:true,"),e.component&&(n+='tag:"'+e.tag+'",');for(var i=0;i<t.dataGenFns.length;i++)n+=t.dataGenFns[i](e);if(e.attrs&&(n+="attrs:{"+io(e.attrs)+"},"),e.props&&(n+="domProps:{"+io(e.props)+"},"),e.events&&(n+=Ii(e.events,!1)+","),e.nativeEvents&&(n+=Ii(e.nativeEvents,!0)+","),e.slotTarget&&!e.slotScope&&(n+="slot:"+e.slotTarget+","),e.scopedSlots&&(n+=Wi(e.scopedSlots,t)+","),e.model&&(n+="model:{value:"+e.model.value+",callback:"+e.model.callback+",expression:"+e.model.expression+"},"),e.inlineTemplate){var o=Ki(e,t);o&&(n+=o+",")}return n=n.replace(/,$/,"")+"}",e.wrapData&&(n=e.wrapData(n)),e.wrapListeners&&(n=e.wrapListeners(n)),n}function qi(e,t){var n=e.directives;if(n){var r,i,o,a,s="directives:[",c=!1;for(r=0,i=n.length;r<i;r++){o=n[r],a=!0;var u=t.directives[o.name];u&&(a=!!u(e,o,t.warn)),a&&(c=!0,s+='{name:"'+o.name+'",rawName:"'+o.rawName+'"'+(o.value?",value:("+o.value+"),expression:"+JSON.stringify(o.value):"")+(o.arg?',arg:"'+o.arg+'"':"")+(o.modifiers?",modifiers:"+JSON.stringify(o.modifiers):"")+"},")}return c?s.slice(0,-1)+"]":void 0}}function Ki(e,t){var n=e.children[0];if(1===n.type){var r=Di(n,t.options);return"inlineTemplate:{render:function(){"+r.render+"},staticRenderFns:["+r.staticRenderFns.map(function(e){return"function(){"+e+"}"}).join(",")+"]}"}}function Wi(e,t){return"scopedSlots:_u(["+Object.keys(e).map(function(n){return Ji(n,e[n],t)}).join(",")+"])"}function Ji(e,t,n){return t.for&&!t.forProcessed?Gi(e,t,n):"{key:"+e+",fn:function("+String(t.slotScope)+"){return "+("template"===t.tag?t.if?"("+t.if+")?"+(Xi(t,n)||"undefined")+":undefined":Xi(t,n)||"undefined":Ui(t,n))+"}}"}function Gi(e,t,n){var r=t.for,i=t.alias,o=t.iterator1?","+t.iterator1:"",a=t.iterator2?","+t.iterator2:"";return t.forProcessed=!0,"_l(("+r+"),function("+i+o+a+"){return "+Ji(e,t,n)+"})"}function Xi(e,t,n,r,i){var o=e.children;if(o.length){var a=o[0];if(1===o.length&&a.for&&"template"!==a.tag&&"slot"!==a.tag){var s=n?t.maybeComponent(a)?",1":",0":"";return""+(r||Ui)(a,t)+s}var c=n?Zi(o,t.maybeComponent):0,u=i||Qi;return"["+o.map(function(e){return u(e,t)}).join(",")+"]"+(c?","+c:"")}}function Zi(e,t){for(var n=0,r=0;r<e.length;r++){var i=e[r];if(1===i.type){if(Yi(i)||i.ifConditions&&i.ifConditions.some(function(e){return Yi(e.block)})){n=2;break}(t(i)||i.ifConditions&&i.ifConditions.some(function(e){return t(e.block)}))&&(n=1)}}return n}function Yi(e){return void 0!==e.for||"template"===e.tag||"slot"===e.tag}function Qi(e,t){return 1===e.type?Ui(e,t):3===e.type&&e.isComment?to(e):eo(e)}function eo(e){return"_v("+(2===e.type?e.expression:oo(JSON.stringify(e.text)))+")"}function to(e){return"_e("+JSON.stringify(e.text)+")"}function no(e,t){var n=e.slotName||'"default"',r=Xi(e,t),i="_t("+n+(r?","+r:""),o=e.attrs&&"{"+e.attrs.map(function(e){return yo(e.name)+":"+e.value}).join(",")+"}",a=e.attrsMap["v-bind"];return!o&&!a||r||(i+=",null"),o&&(i+=","+o),a&&(i+=(o?"":",null")+","+a),i+")"}function ro(e,t,n){var r=t.inlineTemplate?null:Xi(t,n,!0);return"_c("+e+","+Vi(t,n)+(r?","+r:"")+")"}function io(e){for(var t="",n=0;n<e.length;n++){var r=e[n];t+='"'+r.name+'":'+oo(r.value)+","}return t.slice(0,-1)}function oo(e){return e.replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}function ao(e,t){try{return new Function(e)}catch(n){return t.push({err:n,code:e}),x}}function so(e){var t=Object.create(null);return function(n,r,i){r=w({},r),r.warn,delete r.warn;var o=r.delimiters?String(r.delimiters)+n:n;if(t[o])return t[o];var a=e(n,r),s={},c=[];return s.render=ao(a.render,c),s.staticRenderFns=a.staticRenderFns.map(function(e){return ao(e,c)}),t[o]=s}}function co(e){return lc=lc||document.createElement("div"),lc.innerHTML=e?'<a href="\n"/>':'<div a="\n"/>',lc.innerHTML.indexOf(" ")>0}function uo(e){if(e.outerHTML)return e.outerHTML;var t=document.createElement("div");return t.appendChild(e.cloneNode(!0)),t.innerHTML}/*!
|
2 |
-
* Vue.js v2.5.22
|
3 |
-
* (c) 2014-2019 Evan You
|
4 |
-
* Released under the MIT License.
|
5 |
-
*/
|
6 |
-
var lo=Object.freeze({}),fo=Object.prototype.toString,po=v("slot,component",!0),vo=v("key,ref,slot,slot-scope,is"),ho=Object.prototype.hasOwnProperty,mo=/-(\w)/g,yo=y(function(e){return e.replace(mo,function(e,t){return t?t.toUpperCase():""})}),go=y(function(e){return e.charAt(0).toUpperCase()+e.slice(1)}),_o=/\B([A-Z])/g,bo=y(function(e){return e.replace(_o,"-$1").toLowerCase()}),wo=Function.prototype.bind?_:g,Co=function(e,t,n){return!1},xo=function(e){return e},$o="data-server-rendered",ko=["component","directive","filter"],So=["beforeCreate","created","beforeMount","mounted","beforeUpdate","updated","beforeDestroy","destroyed","activated","deactivated","errorCaptured"],Ao={optionMergeStrategies:Object.create(null),silent:!1,productionTip:!1,devtools:!1,performance:!1,errorHandler:null,warnHandler:null,ignoredElements:[],keyCodes:Object.create(null),isReservedTag:Co,isReservedAttr:Co,isUnknownElement:Co,getTagNamespace:x,parsePlatformTagName:xo,mustUseProp:Co,async:!0,_lifecycleHooks:So},To=/[^\w.$]/,Oo="__proto__"in{},Eo="undefined"!=typeof window,Io="undefined"!=typeof WXEnvironment&&!!WXEnvironment.platform,Lo=Io&&WXEnvironment.platform.toLowerCase(),jo=Eo&&window.navigator.userAgent.toLowerCase(),Po=jo&&/msie|trident/.test(jo),Ro=jo&&jo.indexOf("msie 9.0")>0,No=jo&&jo.indexOf("edge/")>0,Do=(jo&&jo.indexOf("android"),jo&&/iphone|ipad|ipod|ios/.test(jo)||"ios"===Lo),Uo=(jo&&/chrome\/\d+/.test(jo),{}.watch),Fo=!1;if(Eo)try{var Mo={};Object.defineProperty(Mo,"passive",{get:function(){Fo=!0}}),window.addEventListener("test-passive",null,Mo)}catch(e){}var Bo,Ho,zo=function(){return void 0===Bo&&(Bo=!Eo&&!Io&&void 0!==e&&e.process&&"server"===e.process.env.VUE_ENV),Bo},Vo=Eo&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,qo="undefined"!=typeof Symbol&&E(Symbol)&&"undefined"!=typeof Reflect&&E(Reflect.ownKeys);Ho="undefined"!=typeof Set&&E(Set)?Set:function(){function e(){this.set=Object.create(null)}return e.prototype.has=function(e){return!0===this.set[e]},e.prototype.add=function(e){this.set[e]=!0},e.prototype.clear=function(){this.set=Object.create(null)},e}();var Ko=x,Wo=0,Jo=function(){this.id=Wo++,this.subs=[]};Jo.prototype.addSub=function(e){this.subs.push(e)},Jo.prototype.removeSub=function(e){h(this.subs,e)},Jo.prototype.depend=function(){Jo.target&&Jo.target.addDep(this)},Jo.prototype.notify=function(){for(var e=this.subs.slice(),t=0,n=e.length;t<n;t++)e[t].update()},Jo.target=null;var Go=[],Xo=function(e,t,n,r,i,o,a,s){this.tag=e,this.data=t,this.children=n,this.text=r,this.elm=i,this.ns=void 0,this.context=o,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=t&&t.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=s,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1},Zo={child:{configurable:!0}};Zo.child.get=function(){return this.componentInstance},Object.defineProperties(Xo.prototype,Zo);var Yo=function(e){void 0===e&&(e="");var t=new Xo;return t.text=e,t.isComment=!0,t},Qo=Array.prototype,ea=Object.create(Qo);["push","pop","shift","unshift","splice","sort","reverse"].forEach(function(e){var t=Qo[e];T(ea,e,function(){for(var n=[],r=arguments.length;r--;)n[r]=arguments[r];var i,o=t.apply(this,n),a=this.__ob__;switch(e){case"push":case"unshift":i=n;break;case"splice":i=n.slice(2)}return i&&a.observeArray(i),a.dep.notify(),o})});var ta=Object.getOwnPropertyNames(ea),na=!0,ra=function(e){this.value=e,this.dep=new Jo,this.vmCount=0,T(e,"__ob__",this),Array.isArray(e)?(Oo?N(e,ea):D(e,ea,ta),this.observeArray(e)):this.walk(e)};ra.prototype.walk=function(e){for(var t=Object.keys(e),n=0;n<t.length;n++)F(e,t[n])},ra.prototype.observeArray=function(e){for(var t=0,n=e.length;t<n;t++)U(e[t])};var ia=Ao.optionMergeStrategies;ia.data=function(e,t,n){return n?V(e,t,n):t&&"function"!=typeof t?e:V(e,t)},So.forEach(function(e){ia[e]=q}),ko.forEach(function(e){ia[e+"s"]=W}),ia.watch=function(e,t,n,r){if(e===Uo&&(e=void 0),t===Uo&&(t=void 0),!t)return Object.create(e||null);if(!e)return t;var i={};w(i,e);for(var o in t){var a=i[o],s=t[o];a&&!Array.isArray(a)&&(a=[a]),i[o]=a?a.concat(s):Array.isArray(s)?s:[s]}return i},ia.props=ia.methods=ia.inject=ia.computed=function(e,t,n,r){if(!e)return t;var i=Object.create(null);return w(i,e),t&&w(i,t),i},ia.provide=V;var oa,aa,sa=function(e,t){return void 0===t?e:t},ca=[],ua=!1,la=!1;if(void 0!==n&&E(n))aa=function(){n(se)};else if("undefined"==typeof MessageChannel||!E(MessageChannel)&&"[object MessageChannelConstructor]"!==MessageChannel.toString())aa=function(){setTimeout(se,0)};else{var fa=new MessageChannel,da=fa.port2;fa.port1.onmessage=se,aa=function(){da.postMessage(1)}}if("undefined"!=typeof Promise&&E(Promise)){var pa=Promise.resolve();oa=function(){pa.then(se),Do&&setTimeout(x)}}else oa=aa;var va,ha=new Ho,ma=y(function(e){var t="&"===e.charAt(0);e=t?e.slice(1):e;var n="~"===e.charAt(0);e=n?e.slice(1):e;var r="!"===e.charAt(0);return e=r?e.slice(1):e,{name:e,once:n,capture:r,passive:t}}),ya=null,ga=[],_a=[],ba={},wa=!1,Ca=!1,xa=0,$a=0,ka=function(e,t,n,r,i){this.vm=e,i&&(e._watcher=this),e._watchers.push(this),r?(this.deep=!!r.deep,this.user=!!r.user,this.lazy=!!r.lazy,this.sync=!!r.sync,this.before=r.before):this.deep=this.user=this.lazy=this.sync=!1,this.cb=n,this.id=++$a,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=new Ho,this.newDepIds=new Ho,this.expression="","function"==typeof t?this.getter=t:(this.getter=O(t),this.getter||(this.getter=x)),this.value=this.lazy?void 0:this.get()};ka.prototype.get=function(){I(this);var e,t=this.vm;try{e=this.getter.call(t,t)}catch(e){if(!this.user)throw e;ie(e,t,'getter for watcher "'+this.expression+'"')}finally{this.deep&&le(e),L(),this.cleanupDeps()}return e},ka.prototype.addDep=function(e){var t=e.id;this.newDepIds.has(t)||(this.newDepIds.add(t),this.newDeps.push(e),this.depIds.has(t)||e.addSub(this))},ka.prototype.cleanupDeps=function(){for(var e=this.deps.length;e--;){var t=this.deps[e];this.newDepIds.has(t.id)||t.removeSub(this)}var n=this.depIds;this.depIds=this.newDepIds,this.newDepIds=n,this.newDepIds.clear(),n=this.deps,this.deps=this.newDeps,this.newDeps=n,this.newDeps.length=0},ka.prototype.update=function(){this.lazy?this.dirty=!0:this.sync?this.run():We(this)},ka.prototype.run=function(){if(this.active){var e=this.get();if(e!==this.value||c(e)||this.deep){var t=this.value;if(this.value=e,this.user)try{this.cb.call(this.vm,e,t)}catch(e){ie(e,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,e,t)}}},ka.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},ka.prototype.depend=function(){for(var e=this.deps.length;e--;)this.deps[e].depend()},ka.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||h(this.vm._watchers,this);for(var e=this.deps.length;e--;)this.deps[e].removeSub(this);this.active=!1}};var Sa={enumerable:!0,configurable:!0,get:x,set:x},Aa={lazy:!0};bt(wt.prototype);var Ta={init:function(e,t){if(e.componentInstance&&!e.componentInstance._isDestroyed&&e.data.keepAlive){var n=e;Ta.prepatch(n,n)}else(e.componentInstance=St(e,ya)).$mount(t?e.elm:void 0,t)},prepatch:function(e,t){var n=t.componentOptions;De(t.componentInstance=e.componentInstance,n.propsData,n.listeners,t,n.children)},insert:function(e){var t=e.context,n=e.componentInstance;n._isMounted||(n._isMounted=!0,Be(n,"mounted")),e.data.keepAlive&&(t._isMounted?qe(n):Fe(n,!0))},destroy:function(e){var t=e.componentInstance;t._isDestroyed||(e.data.keepAlive?Me(t,!0):t.$destroy())}},Oa=Object.keys(Ta),Ea=1,Ia=2,La=0;!function(e){e.prototype._init=function(e){var t=this;t._uid=La++,t._isVue=!0,e&&e._isComponent?Rt(t,e):t.$options=Z(Nt(t.constructor),e||{},t),t._renderProxy=t,t._self=t,Re(t),Se(t),Pt(t),Be(t,"beforeCreate"),st(t),Ge(t),at(t),Be(t,"created"),t.$options.el&&t.$mount(t.$options.el)}}(Ut),function(e){var t={};t.get=function(){return this._data};var n={};n.get=function(){return this._props},Object.defineProperty(e.prototype,"$data",t),Object.defineProperty(e.prototype,"$props",n),e.prototype.$set=M,e.prototype.$delete=B,e.prototype.$watch=function(e,t,n){var r=this;if(u(t))return ot(r,e,t,n);n=n||{},n.user=!0;var i=new ka(r,e,t,n);if(n.immediate)try{t.call(r,i.value)}catch(e){ie(e,r,'callback for immediate watcher "'+i.expression+'"')}return function(){i.teardown()}}}(Ut),function(e){var t=/^hook:/;e.prototype.$on=function(e,n){var r=this;if(Array.isArray(e))for(var i=0,o=e.length;i<o;i++)r.$on(e[i],n);else(r._events[e]||(r._events[e]=[])).push(n),t.test(e)&&(r._hasHookEvent=!0);return r},e.prototype.$once=function(e,t){function n(){r.$off(e,n),t.apply(r,arguments)}var r=this;return n.fn=t,r.$on(e,n),r},e.prototype.$off=function(e,t){var n=this;if(!arguments.length)return n._events=Object.create(null),n;if(Array.isArray(e)){for(var r=0,i=e.length;r<i;r++)n.$off(e[r],t);return n}var o=n._events[e];if(!o)return n;if(!t)return n._events[e]=null,n;for(var a,s=o.length;s--;)if((a=o[s])===t||a.fn===t){o.splice(s,1);break}return n},e.prototype.$emit=function(e){var t=this,n=t._events[e];if(n){n=n.length>1?b(n):n;for(var r=b(arguments,1),i=0,o=n.length;i<o;i++)try{n[i].apply(t,r)}catch(n){ie(n,t,'event handler for "'+e+'"')}}return t}}(Ut),function(e){e.prototype._update=function(e,t){var n=this,r=n.$el,i=n._vnode,o=Pe(n);n._vnode=e,n.$el=i?n.__patch__(i,e):n.__patch__(n.$el,e,t,!1),o(),r&&(r.__vue__=null),n.$el&&(n.$el.__vue__=n),n.$vnode&&n.$parent&&n.$vnode===n.$parent._vnode&&(n.$parent.$el=n.$el)},e.prototype.$forceUpdate=function(){var e=this;e._watcher&&e._watcher.update()},e.prototype.$destroy=function(){var e=this;if(!e._isBeingDestroyed){Be(e,"beforeDestroy"),e._isBeingDestroyed=!0;var t=e.$parent;!t||t._isBeingDestroyed||e.$options.abstract||h(t.$children,e),e._watcher&&e._watcher.teardown();for(var n=e._watchers.length;n--;)e._watchers[n].teardown();e._data.__ob__&&e._data.__ob__.vmCount--,e._isDestroyed=!0,e.__patch__(e._vnode,null),Be(e,"destroyed"),e.$off(),e.$el&&(e.$el.__vue__=null),e.$vnode&&(e.$vnode.parent=null)}}}(Ut),function(e){bt(e.prototype),e.prototype.$nextTick=function(e){return ue(e,this)},e.prototype._render=function(){var e=this,t=e.$options,n=t.render,r=t._parentVnode;r&&(e.$scopedSlots=r.data.scopedSlots||lo),e.$vnode=r;var i;try{i=n.call(e._renderProxy,e.$createElement)}catch(t){ie(t,e,"render"),i=e._vnode}return i instanceof Xo||(i=Yo()),i.parent=r,i}}(Ut);var ja=[String,RegExp,Array],Pa={name:"keep-alive",abstract:!0,props:{include:ja,exclude:ja,max:[String,Number]},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var e in this.cache)Jt(this.cache,e,this.keys)},mounted:function(){var e=this;this.$watch("include",function(t){Wt(e,function(e){return Kt(t,e)})}),this.$watch("exclude",function(t){Wt(e,function(e){return!Kt(t,e)})})},render:function(){var e=this.$slots.default,t=ke(e),n=t&&t.componentOptions;if(n){var r=qt(n),i=this,o=i.include,a=i.exclude;if(o&&(!r||!Kt(o,r))||a&&r&&Kt(a,r))return t;var s=this,c=s.cache,u=s.keys,l=null==t.key?n.Ctor.cid+(n.tag?"::"+n.tag:""):t.key;c[l]?(t.componentInstance=c[l].componentInstance,h(u,l),u.push(l)):(c[l]=t,u.push(l),this.max&&u.length>parseInt(this.max)&&Jt(c,u[0],u,this._vnode)),t.data.keepAlive=!0}return t||e&&e[0]}},Ra={KeepAlive:Pa};!function(e){var t={};t.get=function(){return Ao},Object.defineProperty(e,"config",t),e.util={warn:Ko,extend:w,mergeOptions:Z,defineReactive:F},e.set=M,e.delete=B,e.nextTick=ue,e.options=Object.create(null),ko.forEach(function(t){e.options[t+"s"]=Object.create(null)}),e.options._base=e,w(e.options.components,Ra),Ft(e),Mt(e),Bt(e),Vt(e)}(Ut),Object.defineProperty(Ut.prototype,"$isServer",{get:zo}),Object.defineProperty(Ut.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(Ut,"FunctionalRenderContext",{value:wt}),Ut.version="2.5.22";var Na,Da,Ua,Fa,Ma,Ba,Ha,za,Va,qa=v("style,class"),Ka=v("input,textarea,option,select,progress"),Wa=function(e,t,n){return"value"===n&&Ka(e)&&"button"!==t||"selected"===n&&"option"===e||"checked"===n&&"input"===e||"muted"===n&&"video"===e},Ja=v("contenteditable,draggable,spellcheck"),Ga=v("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,translate,truespeed,typemustmatch,visible"),Xa="http://www.w3.org/1999/xlink",Za=function(e){return":"===e.charAt(5)&&"xlink"===e.slice(0,5)},Ya=function(e){return Za(e)?e.slice(6,e.length):""},Qa=function(e){return null==e||!1===e},es={svg:"http://www.w3.org/2000/svg",math:"http://www.w3.org/1998/Math/MathML"},ts=v("html,body,base,head,link,meta,style,title,address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,menuitem,summary,content,element,shadow,template,blockquote,iframe,tfoot"),ns=v("svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view",!0),rs=function(e){return"pre"===e},is=function(e){return ts(e)||ns(e)},os=Object.create(null),as=v("text,number,password,search,email,tel,url"),ss=Object.freeze({createElement:an,createElementNS:sn,createTextNode:cn,createComment:un,insertBefore:ln,removeChild:fn,appendChild:dn,parentNode:pn,nextSibling:vn,tagName:hn,setTextContent:mn,setStyleScope:yn}),cs={create:function(e,t){gn(t)},update:function(e,t){e.data.ref!==t.data.ref&&(gn(e,!0),gn(t))},destroy:function(e){gn(e,!0)}},us=new Xo("",{},[]),ls=["create","activate","update","remove","destroy"],fs={create:Cn,update:Cn,destroy:function(e){Cn(e,us)}},ds=Object.create(null),ps=[cs,fs],vs={create:An,update:An},hs={create:En,update:En},ms=/[\w).+\-_$\]]/,ys="__r",gs="__c",_s={create:or,update:or},bs={create:ar,update:ar},ws=y(function(e){var t={},n=/;(?![^(]*\))/g,r=/:(.+)/;return e.split(n).forEach(function(e){if(e){var n=e.split(r);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}),Cs=/^--/,xs=/\s*!important$/,$s=function(e,t,n){if(Cs.test(t))e.style.setProperty(t,n);else if(xs.test(n))e.style.setProperty(t,n.replace(xs,""),"important");else{var r=Ss(t);if(Array.isArray(n))for(var i=0,o=n.length;i<o;i++)e.style[r]=n[i];else e.style[r]=n}},ks=["Webkit","Moz","ms"],Ss=y(function(e){if(Va=Va||document.createElement("div").style,"filter"!==(e=yo(e))&&e in Va)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=0;n<ks.length;n++){var r=ks[n]+t;if(r in Va)return r}}),As={create:pr,update:pr},Ts=/\s+/,Os=y(function(e){return{enterClass:e+"-enter",enterToClass:e+"-enter-to",enterActiveClass:e+"-enter-active",leaveClass:e+"-leave",leaveToClass:e+"-leave-to",leaveActiveClass:e+"-leave-active"}}),Es=Eo&&!Ro,Is="transition",Ls="animation",js="transition",Ps="transitionend",Rs="animation",Ns="animationend";Es&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(js="WebkitTransition",Ps="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(Rs="WebkitAnimation",Ns="webkitAnimationEnd"));var Ds=Eo?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(e){return e()},Us=/\b(transform|all)(,|$)/,Fs=Eo?{create:Tr,activate:Tr,remove:function(e,t){!0!==e.data.show?kr(e,t):t()}}:{},Ms=[vs,hs,_s,bs,As,Fs],Bs=Ms.concat(ps),Hs=function(e){function t(e){return new Xo(I.tagName(e).toLowerCase(),{},[],void 0,e)}function n(e,t){function n(){0==--n.listeners&&a(e)}return n.listeners=t,n}function a(e){var t=I.parentNode(e);i(t)&&I.removeChild(t,e)}function c(e,t,n,r,a,s,c){if(i(e.elm)&&i(s)&&(e=s[c]=P(e)),e.isRootInsert=!a,!u(e,t,n,r)){var l=e.data,f=e.children,v=e.tag;i(v)?(e.elm=e.ns?I.createElementNS(e.ns,v):I.createElement(v,e),y(e),p(e,f,t),i(l)&&m(e,t),d(n,e.elm,r)):o(e.isComment)?(e.elm=I.createComment(e.text),d(n,e.elm,r)):(e.elm=I.createTextNode(e.text),d(n,e.elm,r))}}function u(e,t,n,r){var a=e.data;if(i(a)){var s=i(e.componentInstance)&&a.keepAlive;if(i(a=a.hook)&&i(a=a.init)&&a(e,!1),i(e.componentInstance))return l(e,t),d(n,e.elm,r),o(s)&&f(e,t,n,r),!0}}function l(e,t){i(e.data.pendingInsert)&&(t.push.apply(t,e.data.pendingInsert),e.data.pendingInsert=null),e.elm=e.componentInstance.$el,h(e)?(m(e,t),y(e)):(gn(e),t.push(e))}function f(e,t,n,r){for(var o,a=e;a.componentInstance;)if(a=a.componentInstance._vnode,i(o=a.data)&&i(o=o.transition)){for(o=0;o<O.activate.length;++o)O.activate[o](us,a);t.push(a);break}d(n,e.elm,r)}function d(e,t,n){i(e)&&(i(n)?I.parentNode(n)===e&&I.insertBefore(e,t,n):I.appendChild(e,t))}function p(e,t,n){if(Array.isArray(t))for(var r=0;r<t.length;++r)c(t[r],n,e.elm,null,!0,t,r);else s(e.text)&&I.appendChild(e.elm,I.createTextNode(String(e.text)))}function h(e){for(;e.componentInstance;)e=e.componentInstance._vnode;return i(e.tag)}function m(e,t){for(var n=0;n<O.create.length;++n)O.create[n](us,e);A=e.data.hook,i(A)&&(i(A.create)&&A.create(us,e),i(A.insert)&&t.push(e))}function y(e){var t;if(i(t=e.fnScopeId))I.setStyleScope(e.elm,t);else for(var n=e;n;)i(t=n.context)&&i(t=t.$options._scopeId)&&I.setStyleScope(e.elm,t),n=n.parent;i(t=ya)&&t!==e.context&&t!==e.fnContext&&i(t=t.$options._scopeId)&&I.setStyleScope(e.elm,t)}function g(e,t,n,r,i,o){for(;r<=i;++r)c(n[r],o,e,t,!1,n,r)}function _(e){var t,n,r=e.data;if(i(r))for(i(t=r.hook)&&i(t=t.destroy)&&t(e),t=0;t<O.destroy.length;++t)O.destroy[t](e);if(i(t=e.children))for(n=0;n<e.children.length;++n)_(e.children[n])}function b(e,t,n,r){for(;n<=r;++n){var o=t[n];i(o)&&(i(o.tag)?(w(o),_(o)):a(o.elm))}}function w(e,t){if(i(t)||i(e.data)){var r,o=O.remove.length+1;for(i(t)?t.listeners+=o:t=n(e.elm,o),i(r=e.componentInstance)&&i(r=r._vnode)&&i(r.data)&&w(r,t),r=0;r<O.remove.length;++r)O.remove[r](e,t);i(r=e.data.hook)&&i(r=r.remove)?r(e,t):t()}else a(e.elm)}function C(e,t,n,o,a){for(var s,u,l,f,d=0,p=0,v=t.length-1,h=t[0],m=t[v],y=n.length-1,_=n[0],w=n[y],C=!a;d<=v&&p<=y;)r(h)?h=t[++d]:r(m)?m=t[--v]:_n(h,_)?($(h,_,o,n,p),h=t[++d],_=n[++p]):_n(m,w)?($(m,w,o,n,y),m=t[--v],w=n[--y]):_n(h,w)?($(h,w,o,n,y),C&&I.insertBefore(e,h.elm,I.nextSibling(m.elm)),h=t[++d],w=n[--y]):_n(m,_)?($(m,_,o,n,p),C&&I.insertBefore(e,m.elm,h.elm),m=t[--v],_=n[++p]):(r(s)&&(s=wn(t,d,v)),u=i(_.key)?s[_.key]:x(_,t,d,v),r(u)?c(_,o,e,h.elm,!1,n,p):(l=t[u],_n(l,_)?($(l,_,o,n,p),t[u]=void 0,C&&I.insertBefore(e,l.elm,h.elm)):c(_,o,e,h.elm,!1,n,p)),_=n[++p]);d>v?(f=r(n[y+1])?null:n[y+1].elm,g(e,f,n,p,y,o)):p>y&&b(e,t,d,v)}function x(e,t,n,r){for(var o=n;o<r;o++){var a=t[o];if(i(a)&&_n(e,a))return o}}function $(e,t,n,a,s,c){if(e!==t){i(t.elm)&&i(a)&&(t=a[s]=P(t));var u=t.elm=e.elm;if(o(e.isAsyncPlaceholder))return void(i(t.asyncFactory.resolved)?S(e.elm,t,n):t.isAsyncPlaceholder=!0);if(o(t.isStatic)&&o(e.isStatic)&&t.key===e.key&&(o(t.isCloned)||o(t.isOnce)))return void(t.componentInstance=e.componentInstance);var l,f=t.data;i(f)&&i(l=f.hook)&&i(l=l.prepatch)&&l(e,t);var d=e.children,p=t.children;if(i(f)&&h(t)){for(l=0;l<O.update.length;++l)O.update[l](e,t);i(l=f.hook)&&i(l=l.update)&&l(e,t)}r(t.text)?i(d)&&i(p)?d!==p&&C(u,d,p,n,c):i(p)?(i(e.text)&&I.setTextContent(u,""),g(u,null,p,0,p.length-1,n)):i(d)?b(u,d,0,d.length-1):i(e.text)&&I.setTextContent(u,""):e.text!==t.text&&I.setTextContent(u,t.text),i(f)&&i(l=f.hook)&&i(l=l.postpatch)&&l(e,t)}}function k(e,t,n){if(o(n)&&i(e.parent))e.parent.data.pendingInsert=t;else for(var r=0;r<t.length;++r)t[r].data.hook.insert(t[r])}function S(e,t,n,r){var a,s=t.tag,c=t.data,u=t.children;if(r=r||c&&c.pre,t.elm=e,o(t.isComment)&&i(t.asyncFactory))return t.isAsyncPlaceholder=!0,!0;if(i(c)&&(i(a=c.hook)&&i(a=a.init)&&a(t,!0),i(a=t.componentInstance)))return l(t,n),!0;if(i(s)){if(i(u))if(e.hasChildNodes())if(i(a=c)&&i(a=a.domProps)&&i(a=a.innerHTML)){if(a!==e.innerHTML)return!1}else{for(var f=!0,d=e.firstChild,v=0;v<u.length;v++){if(!d||!S(d,u[v],n,r)){f=!1;break}d=d.nextSibling}if(!f||d)return!1}else p(t,u,n);if(i(c)){var h=!1;for(var y in c)if(!L(y)){h=!0,m(t,n);break}!h&&c.class&&le(c.class)}}else e.data!==t.text&&(e.data=t.text);return!0}var A,T,O={},E=e.modules,I=e.nodeOps;for(A=0;A<ls.length;++A)for(O[ls[A]]=[],T=0;T<E.length;++T)i(E[T][ls[A]])&&O[ls[A]].push(E[T][ls[A]]);var L=v("attrs,class,staticClass,staticStyle,key");return function(e,n,a,s){if(r(n))return void(i(e)&&_(e));var u=!1,l=[];if(r(e))u=!0,c(n,l);else{var f=i(e.nodeType);if(!f&&_n(e,n))$(e,n,l,null,null,s);else{if(f){if(1===e.nodeType&&e.hasAttribute($o)&&(e.removeAttribute($o),a=!0),o(a)&&S(e,n,l))return k(n,l,!0),e;e=t(e)}var d=e.elm,p=I.parentNode(d);if(c(n,l,d._leaveCb?null:p,I.nextSibling(d)),i(n.parent))for(var v=n.parent,m=h(n);v;){for(var y=0;y<O.destroy.length;++y)O.destroy[y](v);if(v.elm=n.elm,m){for(var g=0;g<O.create.length;++g)O.create[g](us,v);var w=v.data.hook.insert;if(w.merged)for(var C=1;C<w.fns.length;C++)w.fns[C]()}else gn(v);v=v.parent}i(p)?b(p,[e],0,0):i(e.tag)&&_(e)}}return k(n,l,u),n.elm}}({nodeOps:ss,modules:Bs});Ro&&document.addEventListener("selectionchange",function(){var e=document.activeElement;e&&e.vmodel&&Rr(e,"input")});var zs={inserted:function(e,t,n,r){"select"===n.tag?(r.elm&&!r.elm._vOptions?ve(n,"postpatch",function(){zs.componentUpdated(e,t,n)}):Or(e,t,n.context),e._vOptions=[].map.call(e.options,Lr)):("textarea"===n.tag||as(e.type))&&(e._vModifiers=t.modifiers,t.modifiers.lazy||(e.addEventListener("compositionstart",jr),e.addEventListener("compositionend",Pr),e.addEventListener("change",Pr),Ro&&(e.vmodel=!0)))},componentUpdated:function(e,t,n){if("select"===n.tag){Or(e,t,n.context);var r=e._vOptions,i=e._vOptions=[].map.call(e.options,Lr);i.some(function(e,t){return!$(e,r[t])})&&(e.multiple?t.value.some(function(e){return Ir(e,i)}):t.value!==t.oldValue&&Ir(t.value,i))&&Rr(e,"change")}}},Vs={bind:function(e,t,n){var r=t.value;n=Nr(n);var i=n.data&&n.data.transition,o=e.__vOriginalDisplay="none"===e.style.display?"":e.style.display;r&&i?(n.data.show=!0,$r(n,function(){e.style.display=o})):e.style.display=r?o:"none"},update:function(e,t,n){var r=t.value;!r!=!t.oldValue&&(n=Nr(n),n.data&&n.data.transition?(n.data.show=!0,r?$r(n,function(){e.style.display=e.__vOriginalDisplay}):kr(n,function(){e.style.display="none"})):e.style.display=r?e.__vOriginalDisplay:"none")},unbind:function(e,t,n,r,i){i||(e.style.display=e.__vOriginalDisplay)}},qs={model:zs,show:Vs},Ks={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]},Ws=function(e){return e.tag||$e(e)},Js=function(e){return"show"===e.name},Gs={name:"transition",props:Ks,abstract:!0,render:function(e){var t=this,n=this.$slots.default;if(n&&(n=n.filter(Ws),n.length)){var r=this.mode,i=n[0];if(Mr(this.$vnode))return i;var o=Dr(i);if(!o)return i;if(this._leaving)return Fr(e,i);var a="__transition-"+this._uid+"-";o.key=null==o.key?o.isComment?a+"comment":a+o.tag:s(o.key)?0===String(o.key).indexOf(a)?o.key:a+o.key:o.key;var c=(o.data||(o.data={})).transition=Ur(this),u=this._vnode,l=Dr(u);if(o.data.directives&&o.data.directives.some(Js)&&(o.data.show=!0),l&&l.data&&!Br(o,l)&&!$e(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=w({},c);if("out-in"===r)return this._leaving=!0,ve(f,"afterLeave",function(){t._leaving=!1,t.$forceUpdate()}),Fr(e,i);if("in-out"===r){if($e(o))return u;var d,p=function(){d()};ve(c,"afterEnter",p),ve(c,"enterCancelled",p),ve(f,"delayLeave",function(e){d=e})}}return i}}},Xs=w({tag:String,moveClass:String},Ks);delete Xs.mode;var Zs={props:Xs,beforeMount:function(){var e=this,t=this._update;this._update=function(n,r){var i=Pe(e);e.__patch__(e._vnode,e.kept,!1,!0),e._vnode=e.kept,i(),t.call(e,n,r)}},render:function(e){for(var t=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,i=this.$slots.default||[],o=this.children=[],a=Ur(this),s=0;s<i.length;s++){var c=i[s];c.tag&&null!=c.key&&0!==String(c.key).indexOf("__vlist")&&(o.push(c),n[c.key]=c,(c.data||(c.data={})).transition=a)}if(r){for(var u=[],l=[],f=0;f<r.length;f++){var d=r[f];d.data.transition=a,d.data.pos=d.elm.getBoundingClientRect(),n[d.key]?u.push(d):l.push(d)}this.kept=e(t,null,u),this.removed=l}return e(t,null,o)},updated:function(){var e=this.prevChildren,t=this.moveClass||(this.name||"v")+"-move";e.length&&this.hasMove(e[0].elm,t)&&(e.forEach(Hr),e.forEach(zr),e.forEach(Vr),this._reflow=document.body.offsetHeight,e.forEach(function(e){if(e.data.moved){var n=e.elm,r=n.style;gr(n,t),r.transform=r.WebkitTransform=r.transitionDuration="",n.addEventListener(Ps,n._moveCb=function e(r){r&&r.target!==n||r&&!/transform$/.test(r.propertyName)||(n.removeEventListener(Ps,e),n._moveCb=null,_r(n,t))})}}))},methods:{hasMove:function(e,t){if(!Es)return!1;if(this._hasMove)return this._hasMove;var n=e.cloneNode();e._transitionClasses&&e._transitionClasses.forEach(function(e){hr(n,e)}),vr(n,t),n.style.display="none",this.$el.appendChild(n);var r=wr(n);return this.$el.removeChild(n),this._hasMove=r.hasTransform}}},Ys={Transition:Gs,TransitionGroup:Zs};Ut.config.mustUseProp=Wa,Ut.config.isReservedTag=is,Ut.config.isReservedAttr=qa,Ut.config.getTagNamespace=nn,Ut.config.isUnknownElement=rn,w(Ut.options.directives,qs),w(Ut.options.components,Ys),Ut.prototype.__patch__=Eo?Hs:x,Ut.prototype.$mount=function(e,t){return e=e&&Eo?on(e):void 0,Ne(this,e,t)},Eo&&setTimeout(function(){Ao.devtools&&Vo&&Vo.emit("init",Ut)},0);var Qs,ec,tc,nc,rc,ic,oc,ac,sc,cc,uc,lc,fc=/\{\{((?:.|\r?\n)+?)\}\}/g,dc=/[-.*+?^${}()|[\]\/\\]/g,pc=y(function(e){var t=e[0].replace(dc,"\\$&"),n=e[1].replace(dc,"\\$&");return new RegExp(t+"((?:.|\\n)+?)"+n,"g")}),vc={staticKeys:["staticClass"],transformNode:Kr,genData:Wr},hc={staticKeys:["staticStyle"],transformNode:Jr,genData:Gr},mc={decode:function(e){return Qs=Qs||document.createElement("div"),Qs.innerHTML=e,Qs.textContent}},yc=v("area,base,br,col,embed,frame,hr,img,input,isindex,keygen,link,meta,param,source,track,wbr"),gc=v("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source"),_c=v("address,article,aside,base,blockquote,body,caption,col,colgroup,dd,details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,title,tr,track"),bc=/^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,wc="[a-zA-Z_][\\w\\-\\.]*",Cc="((?:"+wc+"\\:)?"+wc+")",xc=new RegExp("^<"+Cc),$c=/^\s*(\/?)>/,kc=new RegExp("^<\\/"+Cc+"[^>]*>"),Sc=/^<!DOCTYPE [^>]+>/i,Ac=/^<!\--/,Tc=/^<!\[/,Oc=v("script,style,textarea",!0),Ec={},Ic={"<":"<",">":">",""":'"',"&":"&"," ":"\n","	":"\t"},Lc=/&(?:lt|gt|quot|amp);/g,jc=/&(?:lt|gt|quot|amp|#10|#9);/g,Pc=v("pre,textarea",!0),Rc=function(e,t){return e&&Pc(e)&&"\n"===t[0]},Nc=/^@|^v-on:/,Dc=/^v-|^@|^:/,Uc=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,Fc=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,Mc=/^\(|\)$/g,Bc=/:(.*)$/,Hc=/^:|^v-bind:/,zc=/\.[^.]+/g,Vc=y(mc.decode),qc=/^xmlns:NS\d+/,Kc=/^NS\d+:/,Wc={preTransformNode:wi},Jc=[vc,hc,Wc],Gc={model:Xn,text:xi,html:$i},Xc={expectHTML:!0,modules:Jc,directives:Gc,isPreTag:rs,isUnaryTag:yc,mustUseProp:Wa,canBeLeftOpenTag:gc,isReservedTag:is,getTagNamespace:nn,staticKeys:function(e){return e.reduce(function(e,t){return e.concat(t.staticKeys||[])},[]).join(",")}(Jc)},Zc=y(Si),Yc=/^([\w$_]+|\([^)]*?\))\s*=>|^function\s*\(/,Qc=/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/,eu={esc:27,tab:9,enter:13,space:32,up:38,left:37,right:39,down:40,delete:[8,46]},tu={esc:["Esc","Escape"],tab:"Tab",enter:"Enter",space:[" ","Spacebar"],up:["Up","ArrowUp"],left:["Left","ArrowLeft"],right:["Right","ArrowRight"],down:["Down","ArrowDown"],delete:["Backspace","Delete","Del"]},nu=function(e){return"if("+e+")return null;"},ru={stop:"$event.stopPropagation();",prevent:"$event.preventDefault();",self:nu("$event.target !== $event.currentTarget"),ctrl:nu("!$event.ctrlKey"),shift:nu("!$event.shiftKey"),alt:nu("!$event.altKey"),meta:nu("!$event.metaKey"),left:nu("'button' in $event && $event.button !== 0"),middle:nu("'button' in $event && $event.button !== 1"),right:nu("'button' in $event && $event.button !== 2")},iu={on:Ri,bind:Ni,cloak:x},ou=function(e){this.options=e,this.warn=e.warn||jn,this.transforms=Pn(e.modules,"transformCode"),this.dataGenFns=Pn(e.modules,"genData"),this.directives=w(w({},iu),e.directives);var t=e.isReservedTag||Co;this.maybeComponent=function(e){return!(t(e.tag)&&!e.component)},this.onceId=0,this.staticRenderFns=[],this.pre=!1},au=(new RegExp("\\b"+"do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,super,throw,while,yield,delete,export,import,return,switch,default,extends,finally,continue,debugger,function,arguments".split(",").join("\\b|\\b")+"\\b"),new RegExp("\\b"+"delete,typeof,void".split(",").join("\\s*\\([^\\)]*\\)|\\b")+"\\s*\\([^\\)]*\\)"),function(e){return function(t){function n(n,r){var i=Object.create(t),o=[],a=[];if(i.warn=function(e,t){(t?a:o).push(e)},r){r.modules&&(i.modules=(t.modules||[]).concat(r.modules)),r.directives&&(i.directives=w(Object.create(t.directives||null),r.directives));for(var s in r)"modules"!==s&&"directives"!==s&&(i[s]=r[s])}var c=e(n,i);return c.errors=o,c.tips=a,c}return{compile:n,compileToFunctions:so(n)}}}(function(e,t){var n=Qr(e.trim(),t);!1!==t.optimize&&ki(n,t);var r=Di(n,t);return{ast:n,render:r.render,staticRenderFns:r.staticRenderFns}})),su=au(Xc),cu=(su.compile,su.compileToFunctions),uu=!!Eo&&co(!1),lu=!!Eo&&co(!0),fu=y(function(e){var t=on(e);return t&&t.innerHTML}),du=Ut.prototype.$mount;Ut.prototype.$mount=function(e,t){if((e=e&&on(e))===document.body||e===document.documentElement)return this;var n=this.$options;if(!n.render){var r=n.template;if(r)if("string"==typeof r)"#"===r.charAt(0)&&(r=fu(r));else{if(!r.nodeType)return this;r=r.innerHTML}else e&&(r=uo(e));if(r){var i=cu(r,{shouldDecodeNewlines:uu,shouldDecodeNewlinesForHref:lu,delimiters:n.delimiters,comments:n.comments},this),o=i.render,a=i.staticRenderFns;n.render=o,n.staticRenderFns=a}}return du.call(this,e,t)},Ut.compile=cu,t.a=Ut}).call(t,n(0),n(4).setImmediate)},function(e,t,n){(function(e){function r(e,t){this._id=e,this._clearFn=t}var i=void 0!==e&&e||"undefined"!=typeof self&&self||window,o=Function.prototype.apply;t.setTimeout=function(){return new r(o.call(setTimeout,i,arguments),clearTimeout)},t.setInterval=function(){return new r(o.call(setInterval,i,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},r.prototype.unref=r.prototype.ref=function(){},r.prototype.close=function(){this._clearFn.call(i,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(5),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(t,n(0))},function(e,t,n){(function(e,t){!function(e,n){"use strict";function r(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n<t.length;n++)t[n]=arguments[n+1];var r={callback:e,args:t};return u[c]=r,s(c),c++}function i(e){delete u[e]}function o(e){var t=e.callback,r=e.args;switch(r.length){case 0:t();break;case 1:t(r[0]);break;case 2:t(r[0],r[1]);break;case 3:t(r[0],r[1],r[2]);break;default:t.apply(n,r)}}function a(e){if(l)setTimeout(a,0,e);else{var t=u[e];if(t){l=!0;try{o(t)}finally{i(e),l=!1}}}}if(!e.setImmediate){var s,c=1,u={},l=!1,f=e.document,d=Object.getPrototypeOf&&Object.getPrototypeOf(e);d=d&&d.setTimeout?d:e,"[object process]"==={}.toString.call(e.process)?function(){s=function(e){t.nextTick(function(){a(e)})}}():function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}}()?function(){var t="setImmediate$"+Math.random()+"$",n=function(n){n.source===e&&"string"==typeof n.data&&0===n.data.indexOf(t)&&a(+n.data.slice(t.length))};e.addEventListener?e.addEventListener("message",n,!1):e.attachEvent("onmessage",n),s=function(n){e.postMessage(t+n,"*")}}():e.MessageChannel?function(){var e=new MessageChannel;e.port1.onmessage=function(e){a(e.data)},s=function(t){e.port2.postMessage(t)}}():f&&"onreadystatechange"in f.createElement("script")?function(){var e=f.documentElement;s=function(t){var n=f.createElement("script");n.onreadystatechange=function(){a(t),n.onreadystatechange=null,e.removeChild(n),n=null},e.appendChild(n)}}():function(){s=function(e){setTimeout(a,0,e)}}(),d.setImmediate=r,d.clearImmediate=i}}("undefined"==typeof self?void 0===e?this:e:self)}).call(t,n(0),n(6))},function(e,t){function n(){throw new Error("setTimeout has not been defined")}function r(){throw new Error("clearTimeout has not been defined")}function i(e){if(l===setTimeout)return setTimeout(e,0);if((l===n||!l)&&setTimeout)return l=setTimeout,setTimeout(e,0);try{return l(e,0)}catch(t){try{return l.call(null,e,0)}catch(t){return l.call(this,e,0)}}}function o(e){if(f===clearTimeout)return clearTimeout(e);if((f===r||!f)&&clearTimeout)return f=clearTimeout,clearTimeout(e);try{return f(e)}catch(t){try{return f.call(null,e)}catch(t){return f.call(this,e)}}}function a(){h&&p&&(h=!1,p.length?v=p.concat(v):m=-1,v.length&&s())}function s(){if(!h){var e=i(a);h=!0;for(var t=v.length;t;){for(p=v,v=[];++m<t;)p&&p[m].run();m=-1,t=v.length}p=null,h=!1,o(e)}}function c(e,t){this.fun=e,this.array=t}function u(){}var l,f,d=e.exports={};!function(){try{l="function"==typeof setTimeout?setTimeout:n}catch(e){l=n}try{f="function"==typeof clearTimeout?clearTimeout:r}catch(e){f=r}}();var p,v=[],h=!1,m=-1;d.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];v.push(new c(e,t)),1!==v.length||h||i(s)},c.prototype.run=function(){this.fun.apply(null,this.array)},d.title="browser",d.browser=!0,d.env={},d.argv=[],d.version="",d.versions={},d.on=u,d.addListener=u,d.once=u,d.off=u,d.removeListener=u,d.removeAllListeners=u,d.emit=u,d.prependListener=u,d.prependOnceListener=u,d.listeners=function(e){return[]},d.binding=function(e){throw new Error("process.binding is not supported")},d.cwd=function(){return"/"},d.chdir=function(e){throw new Error("process.chdir is not supported")},d.umask=function(){return 0}}])});
|
1 |
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.WPRA=t():e.WPRA=t()}("undefined"!=typeof self?self:this,function(){return webpackJsonpWPRA([2],{11:function(e,t,i){"use strict";function s(e,t){for(var i=(arguments.length>2&&void 0!==arguments[2]&&arguments[2],new FormData),s=Object.keys(t),n=Array.isArray(s),r=0,s=n?s:s[Symbol.iterator]();;){var a;if(n){if(r>=s.length)break;a=s[r++]}else{if(r=s.next(),r.done)break;a=r.value}var o=a;i.set(o,t[o])}return fetch(e,{method:"post",body:i}).then(function(e){return e.json()}).then(function(e){if(200!==e.status)throw e;return e})}function n(e){if(!navigator.clipboard)return void g(e);navigator.clipboard.writeText(e).then(function(){},function(e){console.error("Async: Could not copy text: ",e)})}Object.defineProperty(t,"__esModule",{value:!0});var r=i(4),a=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{staticClass:"wizard-holder animated fadeIn"},[i("div",{staticClass:"connect-steps"},[i("div",{staticClass:"step-items"},[i("div",{staticClass:"step-progress",class:"step-progress--"+e.activeScreenIndex}),e._v(" "),e._l(e.screens,function(t,s){return i("div",{staticClass:"step-item",class:{"step-item_active":e.active(t.id),"step-item_completed":t.completed()&&s<e.activeScreenIndex}},[i("div",{staticClass:"step-item__status"},[t.completed()&&s<e.activeScreenIndex?i("span",{staticClass:"dashicons dashicons-yes"}):e._e()]),e._v(" "),i("div",{staticClass:"step-item__info"},[i("div",{staticClass:"step-item__title"},[e._v(e._s(t.title))]),e._v(" "),t.description?i("div",{staticClass:"step-item__description"},[e._v(e._s(t.description))]):e._e()])])})],2)]),e._v(" "),i("div",{staticClass:"wizard"},[i("transition",{attrs:{name:e.transition,mode:"out-in"}},[e.active("feed")?i("div",{key:e.activeScreen,staticClass:"wizard_content"},[i("div",{staticClass:"wizard_hello"},[e._v("\n Enter your first RSS Feed URL\n ")]),e._v(" "),i("form",{staticClass:"wizard_info",attrs:{id:"feedForm"},on:{submit:function(t){return t.preventDefault(),e.next(t)}}},[i("div",{staticClass:"form-group"},[i("input",{directives:[{name:"model",rawName:"v-model",value:e.form.feedSourceUrl,expression:"form.feedSourceUrl"}],staticClass:"wpra-feed-input",attrs:{type:"text",placeholder:"https://www.sourcedomain.com/feed/"},domProps:{value:e.form.feedSourceUrl},on:{input:function(t){t.target.composing||e.$set(e.form,"feedSourceUrl",t.target.value)}}}),e._v(" "),e.isFeedError?i("span",{staticClass:"dashicons dashicons-warning warning-icon"}):e._e(),e._v(" "),e.isFeedError?i("a",{attrs:{href:e.validateLink,target:"_blank"}},[e._v("Validate feed")]):e._e()])]),e._v(" "),e.isFeedError?i("div",{staticClass:"wizard_error"},[i("p",[e._v("This RSS feed URL appears to be invalid. Here are a couple of things you can try:")]),e._v(" "),i("ol",[i("li",[e._v('Check whether the URL you entered is the correct one by trying one of the options when clicking on "How do I find an RSS feed URL?" below.')]),e._v(" "),i("li",[e._v("\n Test out this other RSS feed URL to make sure the plugin is working correctly - https://www.wpmayor.com/feed/ - If it works, you may "),i("a",{attrs:{href:e.supportUrl,target:"_blank"}},[e._v("contact us here")]),e._v(" to help you with your source.\n ")]),e._v(" "),i("li",[e._v("Test the URL's validity by W3C standards, the standards we use in our plugins, using the “Validate feed” link above.")])])]):e._e(),e._v(" "),i("expander",{attrs:{title:"How do I find an RSS feed URL?"}},[i("p",[e._v("WP RSS Aggregator fetches feed items through RSS feeds. Almost every website in the world provides an RSS feed. Here's how to find it:")]),e._v(" "),i("p",[e._v("Option 1: Add /feed to the website's homepage URL ")]),e._v(" "),i("p",[e._v("Many sites have their RSS feed at the same URL. For instance, if the website's URL is www.thiswebsite.com, then the RSS feed could be at www.thiswebsite.com/feed.")]),e._v(" "),i("p",[e._v("Option 2: Look for the RSS share icon")]),e._v(" "),i("p",[e._v("Many websites have share icons on their pages for Facebook, Twitter and more. Many times, there will also be an orange RSS icon. Click on that to access the RSS feed URL.")]),e._v(" "),i("p",[e._v("Option 3: Browser RSS Auto-Discovery")]),e._v(" "),i("p",[e._v("Most browsers either include an RSS auto-discovery tool by default or they allow you to add extensions for it. Firefox shows an RSS icon above the website, in the address bar, which you can click on directly. Chrome offers extensions such as this one.")]),e._v(" "),i("p",[e._v("Option 4: Look at the Page Source")]),e._v(" "),i("p",[e._v('When on any page of the website you\'re looking to import feed items from, right click and press "View Page Source". Once the new window opens, use the “Find” feature (Ctrl-F on PC, Command-F on Mac) and search for " RSS". This should take you to a line that reads like this (or similar):')]),e._v(" "),i("p",[i("code",[e._v('\n <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="https://www.sourcedomain.com/feed/" />\n ')])]),e._v(" "),i("p",[e._v("The RSS feed’s URL is found between the quotes after href=. In the above case, it would be https://www.sourcedomain.com/feed/.")]),e._v(" "),i("p",[i("a",{attrs:{href:e.knowledgeBaseUrl,target:"_blank"}},[e._v("Browse our Knowledge Base for more information.")])])])],1):e._e(),e._v(" "),e.active("feedItems")?i("div",{key:e.activeScreen,staticClass:"wizard_content"},[i("div",{staticClass:"wizard_hello"},[e._v("\n Latest feed items from your selected feed source:\n ")]),e._v(" "),i("div",{staticClass:"wpra-feed-items"},e._l(e.feed.items,function(t){return i("div",{staticClass:"wpra-feed-item"},[i("div",{staticClass:"wpra-feed-item__link"},[i("a",{attrs:{href:t.permalink,target:"_blank"}},[e._v(e._s(t.title))])]),e._v(" "),i("div",{staticClass:"wpra-feed-item__info"},[t.date||t.author?[t.date?[e._v("\n Published on "+e._s(t.date)+"\n ")]:e._e(),e._v(" "),t.date&&t.author?[e._v("|")]:e._e(),e._v(" "),t.author?[e._v("\n By "+e._s(t.author)+"\n ")]:e._e()]:e._e()],2)])}),0),e._v(" "),i("div",{staticClass:"wrpa-shortcode"},[i("div",{staticClass:"wrpa-shortcode-preview"},[i("div",{staticClass:"wrpa-shortcode-label"},[e._v("\n Create a draft page to preview these feed items on your site:\n ")]),e._v(" "),i("a",{staticClass:"button",class:{"button-primary":e.isPrepared,"loading-button":e.isPreparing},attrs:{href:e.previewUrl,target:"_blank"},on:{click:e.preparePreview}},[e._v("\n "+e._s(e.isPrepared?"Preview the Page":"Create Draft Page")+"\n ")])]),e._v(" "),i("div",{staticClass:"wrpa-shortcode-form",on:{click:function(t){return e.copyToClipboard()}}},[i("div",{staticClass:"wrpa-shortcode-label"},[e._v("\n Copy the shortcode to any page or post on your site:\n ")]),e._v(" "),i("input",{ref:"selected",staticClass:"wrpa-shortcode-form__shortcode",attrs:{type:"text",readonly:"",value:"[wp-rss-aggregator]"}}),e._v(" "),i("div",{staticClass:"wrpa-shortcode-form__button"},[e._v("\n "+e._s(e.isCopied?"Copied!":"Click to copy")+"\n ")])])])]):e._e(),e._v(" "),e.active("finish")?i("div",{key:e.activeScreen,staticClass:"wizard_content"},[i("div",{staticClass:"wizard_hello"},[e._v("\n You’ve successfully set up your first feed source 😄\n ")]),e._v(" "),i("div",{staticClass:"wpra-cols-title"},[e._v("\n Do more with WP RSS Aggregator - here is what we did at CryptoHeadlines.com.\n ")]),e._v(" "),i("div",{staticClass:"wpra-cols"},[i("div",{staticClass:"col"},[i("p",[e._v("CryptoHeadlines.com displays latest news, Youtube videos, podcasts, jobs and more from the Cryptocurrency industry.")]),e._v(" "),i("p",[e._v("It uses Feed to Post to import articles, Youtube videos, and podcast links.")]),e._v(" "),i("p",[e._v("Full Text RSS Feeds is used to fetch the full content of the job listings to present more information to the potential applicant.")]),e._v(" "),i("p",[e._v("Keyword Filtering is used to filter out content that contains profanity and keywords or phrases deemed as inappropriate.")]),e._v(" "),i("div",{staticStyle:{"margin-bottom":".5rem"}},[i("a",{staticClass:"button",attrs:{href:e.addOnsUrl,target:"_blank"}},[e._v("\n Browse Add-ons ⭐️\n ")])]),e._v(" "),i("div",[i("a",{staticStyle:{"font-size":".9em"},attrs:{href:e.supportUrl,target:"_blank"}},[e._v("Contact support for more information.")])])]),e._v(" "),i("div",{staticClass:"col"},[i("img",{staticClass:"img wpra-demo-photo",attrs:{src:e.demoImageUrl}}),e._v(" "),i("div",{staticClass:"wpra-feedback"},[i("div",{staticClass:"wpra-feedback__copy"},[i("div",{staticClass:"wpra-feedback__text"},[e._v("\n This plugin has made my life a lot easier, and the support has been great as well.\n ")]),e._v(" "),i("div",{staticClass:"wpra-feedback__rating"},[i("span",{staticClass:"dashicons dashicons-star-filled"}),e._v(" "),i("span",{staticClass:"dashicons dashicons-star-filled"}),e._v(" "),i("span",{staticClass:"dashicons dashicons-star-filled"}),e._v(" "),i("span",{staticClass:"dashicons dashicons-star-filled"}),e._v(" "),i("span",{staticClass:"dashicons dashicons-star-filled"})]),e._v(" "),i("div",{staticClass:"wpra-feedback__by"},[i("a",{attrs:{href:e.feedbackUrl,target:"_blank"}},[e._v("\n Review by officeinnovator\n ")])])])])])])]):e._e()]),e._v(" "),i("div",{staticClass:"connect-actions pad"},[i("div",{staticClass:"pad-item--grow"},[e.active("finish")?e._e():i("button",{staticClass:"button-clear",on:{click:e.finish}},[e._v("\n Skip the introduction\n ")])]),e._v(" "),i("div",{staticClass:"pad-item--no-shrink"},[e.isBackAvailable?i("button",{staticClass:"button-clear",on:{click:e.back}},[e._v("\n Back\n ")]):e._e(),e._v(" "),i("button",{staticClass:"button button-primary button-large",class:{"loading-button":e.isLoading},on:{click:e.next}},[e._v("\n "+e._s(e.active("finish")?"Continue to Plugin":"Next")+"\n ")])])])],1)])},o=[],d=function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("div",{staticClass:"wpra-expander",class:{"wpra-expander--expanded":e.isExpanded}},[i("div",{staticClass:"wpra-expander__title",on:{click:function(t){e.isExpanded=!e.isExpanded}}},[e._v("\n "+e._s(e.title)+"\n "),i("span",{staticClass:"dashicons dashicons-arrow-down-alt2"})]),e._v(" "),i("transition-expand",[e.isExpanded?i("div",[i("div",{staticClass:"wpra-expander__content"},[e._t("default")],2)]):e._e()])],1)},c=[],l={name:"TransitionExpand",functional:!0,render:function(e,t){return e("transition",{props:{name:"expand"},on:{afterEnter:function(e){e.style.height="auto"},enter:function(e){var t=getComputedStyle(e),i=t.width;e.style.width=i,e.style.position="absolute",e.style.visibility="hidden",e.style.height="auto";var s=getComputedStyle(e),n=s.height;e.style.width=null,e.style.position=null,e.style.visibility=null,e.style.height=0,getComputedStyle(e).height,setTimeout(function(){e.style.height=n})},leave:function(e){var t=getComputedStyle(e),i=t.height;e.style.height=i,getComputedStyle(e).height,setTimeout(function(){e.style.height=0})}}},t.children)}},u=l,p=i(1),f=Object(p.a)(u,void 0,void 0,!1,null,null,null),v=f.exports,h={data:function(){return{isExpanded:this.defaultExpanded}},props:{title:{},defaultExpanded:{value:!1}},components:{TransitionExpand:v}},_=h,m=Object(p.a)(_,d,c,!1,null,null,null),w=m.exports,g=function(e){var t=document.createElement("textarea");t.value=e,document.body.appendChild(t),t.focus(),t.select();try{document.execCommand("copy")}catch(e){console.error("Fallback: Oops, unable to copy",e)}document.body.removeChild(t)},y=function(e){return e},b=window.wprssWizardConfig,C={data:function(){var e=this;return{prevHeight:0,screens:[{id:"feed",title:y("Add feed source URL"),description:!1,next:this.submitFeed,completed:function(){return e.feed.items.length},entered:function(){e.focusOnInput("feed")}},{id:"feedItems",title:y("Display feed items"),description:!1,next:this.continueItems,completed:function(){return e.feed.items.length&&e.itemsPassed}},{id:"finish",title:y("Complete introduction"),description:!1,next:this.completeIntroduction,completed:function(){return e.feed.items.length&&e.itemsPassed}}],isCopied:!1,isPreparing:!1,isPrepared:!1,transition:"slide-up",activeScreen:"feed",form:{feedSourceUrl:null},itemsPassed:!1,stepLoading:!1,isLoading:!1,isFeedError:!1,feed:{items:[]},previewUrl:b.previewUrl,addOnsUrl:b.addOnsUrl,supportUrl:b.supportUrl,demoImageUrl:b.demoImageUrl,feedbackUrl:b.feedbackUrl,knowledgeBaseUrl:b.knowledgeBaseUrl}},computed:{validateLink:function(){return"https://validator.w3.org/feed/check.cgi?url="+encodeURI(this.form.feedSourceUrl)},activeScreenIndex:function(){var e=this;return this.screens.findIndex(function(t){return t.id===e.activeScreen})},currentScreen:function(){var e=this;return this.screens.find(function(t){return t.id===e.activeScreen})},actionCompleted:function(){return this.currentScreen.completed()},isBackAvailable:function(){return this.activeScreenIndex>0&&this.activeScreenIndex<this.screens.length}},mounted:function(){this.onScreenEnter()},methods:{preparePreview:function(e){var t=this;if(this.isPreparing)return void e.preventDefault();this.isPrepared||(e.preventDefault(),this.isPreparing=!0,fetch(this.previewUrl).then(function(){t.isPreparing=!1,t.isPrepared=!0}))},submitFeed:function(){var e=this,t=Object.assign(b.feedEndpoint.defaultPayload,{wprss_intro_feed_url:this.form.feedSourceUrl});return this.isLoading=!0,this.isFeedError=!1,s(b.feedEndpoint.url,t).then(function(t){return e.feed.items=t.data.feed_items.slice(0,3),e.isLoading=!1,{}}).catch(function(t){throw e.isLoading=!1,e.isFeedError=!0,t})},continueItems:function(){return this.itemsPassed=!0,Promise.resolve({})},completeIntroduction:function(){return Promise.resolve({})},next:function(){var e=this;this.transition="slide-up";var t=this.currentScreen.next?this.currentScreen.next:function(){return Promise.resolve(!1)};this.stepLoading=!0,t().then(function(t){e.stepLoading=!1},function(e){throw e}).then(function(){var t=e.activeScreenIndex+1;t>=e.screens.length?e.finish():(e.activeScreen=e.screens[t].id,e.onScreenEnter())}).catch(function(e){console.error(e)})},onScreenEnter:function(){var e=this;this.$nextTick(function(){e.currentScreen.entered&&e.currentScreen.entered()})},focusOnInput:function(e){if(!this.$refs[e]||!this.$refs[e].focus)return!1;this.$refs[e].focus()},back:function(){this.transition="slide-down",this.activeScreen=this.screens[this.activeScreenIndex-1].id},finish:function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=function(){return window.location.href=b.feedListUrl};if(e)return void(confirm("Are you sure you want to skip the introduction?")&&t());t()},active:function(e){return this.activeScreen===e},copyToClipboard:function(){var e=this;this.isCopied||(n("[wp-rss-aggregator]"),this.isCopied=!0,setTimeout(function(){e.isCopied=!1},1e3))}},components:{Expander:w}},S=C,k=Object(p.a)(S,a,o,!1,null,null,null),x=k.exports;i(15),i(12),new r.a({el:"#wpra-wizard-app",template:"<Wizard/>",components:{Wizard:x}})},12:function(e,t){}},[11])});
|
|
|
|
|
|
|
|
|
|
js/plugins.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.WPRA=t():e.WPRA=t()}("undefined"!=typeof self?self:this,function(){return webpackJsonpWPRA([1],{16:function(e,t,o){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var a=o(4),n=function(){var e=this,t=e.$createElement,o=e._self._c||t;return o("div",{staticClass:"wpra-plugin-disable-poll"},[o("modal",{attrs:{active:e.isModalVisible,"header-class":"invisible-header"},on:{close:e.closeModal}},[o("div",{attrs:{slot:"header"},slot:"header"},[o("div",{staticClass:"wpra-plugin-disable-poll__logo"},[o("img",{attrs:{src:e.image("light-line-logo.png"),alt:""}})]),e._v(" "),o("h3",[e._v("\n Do you have a moment to share why you are deactivating WP RSS Aggregator?\n ")]),e._v(" "),o("p",[e._v("\n Your feedback will help us to improve our plugins and service.\n ")])]),e._v(" "),o("div",{attrs:{slot:"body"},slot:"body"},[o("SerializedForm",{attrs:{form:e.form},model:{value:e.model,callback:function(t){e.model=t},expression:"model"}})],1),e._v(" "),o("div",{attrs:{slot:"footer"},slot:"footer"},[o("div",{staticClass:"footer-confirm__buttons"},[o("button",{staticClass:"button button-clear",on:{click:e.deactivate}},[e._v("\n Skip & Deactivate\n ")]),e._v(" "),o("button",{staticClass:"button button-primary",class:{"loading-button":e.isDeactivating},on:{click:e.submit}},[e._v("\n Submit & Deactivate\n ")])])])])],1)},i=[],l=function(){var e=this,t=e.$createElement,o=e._self._c||t;return o("transition",{attrs:{name:"modal-transition"}},[e.active?o("div",{staticClass:"modal",on:{click:function(t){return t.target!==t.currentTarget?null:e.$emit("close")}}},[o("div",{class:["modal__body",this.modalBodyClass]},[o("div",{staticClass:"modal__header",class:e.headerClass},[e._t("header")],2),e._v(" "),o("div",{staticClass:"modal__content"},[e._t("body")],2),e._v(" "),o("div",{staticClass:"modal__footer"},[e._t("footer")],2)])]):e._e()])},s=[],r={props:{active:{type:Boolean},title:{type:String},modalBodyClass:{type:String,default:""},headerClass:{default:function(){return{}}},dialogOpenedClass:{type:String,default:"modal-opened"}},watch:{active:function(e){this.$emit(e?"open":"close")}},mounted:function(){var e=this;this.$on("open",function(){document.querySelector("body").classList.add(e.dialogOpenedClass)}),this.$on("close",function(){document.querySelector("body").classList.remove(e.dialogOpenedClass)})}},d=r,c=o(1),u=Object(c.a)(d,l,s,!1,null,null,null),m=u.exports,v=function(){var e=this,t=e.$createElement,o=e._self._c||t;return o("div",{staticClass:"form"},e._l(e.form,function(t){return e.satisfiesCondition(t)?o("div",{staticClass:"form-group"},["radio"===t.type?[t.label?o("label",{attrs:{for:t.name},domProps:{innerHTML:e._s(t.label)}}):e._e(),e._v(" "),e._l(t.options,function(a,n){return o("div",{staticClass:"form-check"},[o("input",{directives:[{name:"model",rawName:"v-model",value:e.model[t.name],expression:"model[datum.name]"}],attrs:{type:"radio",name:t.name,id:t.name+"_"+n},domProps:{value:a.value,checked:e._q(e.model[t.name],a.value)},on:{change:function(o){return e.$set(e.model,t.name,a.value)}}}),e._v(" "),o("label",{attrs:{for:t.name+"_"+n}},[e._v("\n "+e._s(a.label||a.value)+"\n ")])])})]:e._e(),e._v(" "),"textarea"===t.type?[t.label?o("label",{attrs:{for:t.name},domProps:{innerHTML:e._s(t.label)}}):e._e(),e._v(" "),o("textarea",{directives:[{name:"model",rawName:"v-model",value:e.model[t.name],expression:"model[datum.name]"}],attrs:{id:t.name},domProps:{value:e.model[t.name]},on:{input:function(o){o.target.composing||e.$set(e.model,t.name,o.target.value)}}})]:e._e(),e._v(" "),"content"===t.type?[o("div",{class:t.className},[o("p",{domProps:{innerHTML:e._s(t.label)}})])]:e._e()],2):e._e()}),0)},p=[],f={props:{form:{type:Array},value:{type:Object}},computed:{model:{get:function(){return this.value},set:function(e){this.$emit("input",e)}}},methods:{satisfiesCondition:function(e){if(!e.condition)return!0;var t=this.getConditionFunction(e.condition.operator);return!!t&&t(e.condition.field,e.condition.value)},getConditionFunction:function(e){var t=this,o={"=":function(e,o){return t.model[e]===o}};return o[e]?o[e]:null}}},_=f,b=Object(c.a)(_,v,p,!1,null,null,null),h=b.exports,g=o(18),y=o.n(g),C=document.querySelector('[data-slug="wp-rss-aggregator"] .deactivate a'),P={components:{Modal:m,SerializedForm:h},data:function(){return{isDeactivating:!1,deactivateUrl:null,submitUrl:WrpaDisablePoll.url,model:WrpaDisablePoll.model,form:WrpaDisablePoll.form,isModalVisible:!1}},watch:{"model.reason":function(){this.model.follow_up=null}},mounted:function(){C.addEventListener("click",this.handleDeactivateClick)},methods:{image:function(e){return WrpaDisablePoll.image+e},handleDeactivateClick:function(e){this.isModalVisible||(e.preventDefault(),this.isModalVisible=!0)},closeModal:function(){this.isModalVisible=!1,this.deactivateUrl=null},submit:function(){var e=this;this.isDeactivating=!0,y.a.post(this.submitUrl,this.model,{headers:{"Content-Type":"application/x-www-form-urlencoded"}}).then(function(){e.deactivate()}).finally(function(){e.isDeactivating=!1})},deactivate:function(){C.click()}}},w=P,D=Object(c.a)(w,n,i,!1,null,null,null),k=D.exports;o(17),new a.a({el:"#wpra-plugins-app",template:"<PluginDisablePoll/>",components:{PluginDisablePoll:k}})},17:function(e,t){}},[16])});
|
js/src/intro/Wizard.vue
CHANGED
@@ -76,24 +76,45 @@
|
|
76 |
<a :href="item.permalink" target="_blank">{{ item.title }}</a>
|
77 |
</div>
|
78 |
<div class="wpra-feed-item__info">
|
79 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
</div>
|
81 |
</div>
|
82 |
</div>
|
83 |
|
84 |
-
<div class="wizard_label">
|
85 |
-
Copy and paste this shortcode to any page or post to display the full list:
|
86 |
-
</div>
|
87 |
-
|
88 |
<div class="wrpa-shortcode">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
<div class="wrpa-shortcode-form" @click="copyToClipboard()">
|
90 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
<div class="wrpa-shortcode-form__button">
|
92 |
-
|
93 |
</div>
|
94 |
</div>
|
95 |
-
OR
|
96 |
-
<a :href="previewUrl" target="_blank">Preview the feed items on a new page</a>
|
97 |
</div>
|
98 |
</div>
|
99 |
|
@@ -183,6 +204,7 @@
|
|
183 |
<script>
|
184 |
import Expander from './Expander'
|
185 |
import { post } from './fetch'
|
|
|
186 |
|
187 |
const _ = (str) => str
|
188 |
|
@@ -208,11 +230,6 @@
|
|
208 |
title: _('Display feed items'),
|
209 |
description: false,
|
210 |
next: this.continueItems,
|
211 |
-
entered: () => {
|
212 |
-
setTimeout(() => {
|
213 |
-
this.copyToClipboard()
|
214 |
-
}, 400)
|
215 |
-
},
|
216 |
completed: () => {
|
217 |
return this.feed.items.length && this.itemsPassed
|
218 |
}
|
@@ -225,6 +242,11 @@
|
|
225 |
return this.feed.items.length && this.itemsPassed
|
226 |
}
|
227 |
}],
|
|
|
|
|
|
|
|
|
|
|
228 |
transition: 'slide-up', // 'slide-down',
|
229 |
|
230 |
activeScreen: 'feed',
|
@@ -271,6 +293,21 @@
|
|
271 |
this.onScreenEnter()
|
272 |
},
|
273 |
methods: {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
274 |
/**
|
275 |
* Submits first feed step.
|
276 |
*
|
@@ -386,13 +423,14 @@
|
|
386 |
},
|
387 |
|
388 |
copyToClipboard () {
|
389 |
-
|
390 |
-
|
391 |
-
this.$refs.selected.select()
|
392 |
-
}
|
393 |
-
catch (e) {
|
394 |
-
console.error(e)
|
395 |
}
|
|
|
|
|
|
|
|
|
|
|
396 |
}
|
397 |
},
|
398 |
components: {
|
76 |
<a :href="item.permalink" target="_blank">{{ item.title }}</a>
|
77 |
</div>
|
78 |
<div class="wpra-feed-item__info">
|
79 |
+
<template v-if="item.date || item.author">
|
80 |
+
<template v-if="item.date">
|
81 |
+
Published on {{ item.date }}
|
82 |
+
</template>
|
83 |
+
<template v-if="item.date && item.author">|</template>
|
84 |
+
<template v-if="item.author">
|
85 |
+
By {{ item.author }}
|
86 |
+
</template>
|
87 |
+
</template>
|
88 |
</div>
|
89 |
</div>
|
90 |
</div>
|
91 |
|
|
|
|
|
|
|
|
|
92 |
<div class="wrpa-shortcode">
|
93 |
+
<div class="wrpa-shortcode-preview">
|
94 |
+
<div class="wrpa-shortcode-label">
|
95 |
+
Create a draft page to preview these feed items on your site:
|
96 |
+
</div>
|
97 |
+
<a :href="previewUrl" target="_blank" class="button"
|
98 |
+
@click="preparePreview"
|
99 |
+
:class="{'button-primary': isPrepared, 'loading-button': isPreparing}"
|
100 |
+
>
|
101 |
+
{{ isPrepared ? 'Preview the Page' : 'Create Draft Page' }}
|
102 |
+
</a>
|
103 |
+
</div>
|
104 |
<div class="wrpa-shortcode-form" @click="copyToClipboard()">
|
105 |
+
<div class="wrpa-shortcode-label">
|
106 |
+
Copy the shortcode to any page or post on your site:
|
107 |
+
</div>
|
108 |
+
<input class="wrpa-shortcode-form__shortcode"
|
109 |
+
type="text"
|
110 |
+
readonly
|
111 |
+
value="[wp-rss-aggregator]"
|
112 |
+
ref="selected"
|
113 |
+
/>
|
114 |
<div class="wrpa-shortcode-form__button">
|
115 |
+
{{ isCopied ? 'Copied!' : 'Click to copy' }}
|
116 |
</div>
|
117 |
</div>
|
|
|
|
|
118 |
</div>
|
119 |
</div>
|
120 |
|
204 |
<script>
|
205 |
import Expander from './Expander'
|
206 |
import { post } from './fetch'
|
207 |
+
import { copyToClipboard } from './copy'
|
208 |
|
209 |
const _ = (str) => str
|
210 |
|
230 |
title: _('Display feed items'),
|
231 |
description: false,
|
232 |
next: this.continueItems,
|
|
|
|
|
|
|
|
|
|
|
233 |
completed: () => {
|
234 |
return this.feed.items.length && this.itemsPassed
|
235 |
}
|
242 |
return this.feed.items.length && this.itemsPassed
|
243 |
}
|
244 |
}],
|
245 |
+
isCopied: false,
|
246 |
+
|
247 |
+
isPreparing: false,
|
248 |
+
isPrepared: false,
|
249 |
+
|
250 |
transition: 'slide-up', // 'slide-down',
|
251 |
|
252 |
activeScreen: 'feed',
|
293 |
this.onScreenEnter()
|
294 |
},
|
295 |
methods: {
|
296 |
+
preparePreview (e) {
|
297 |
+
if (this.isPreparing) {
|
298 |
+
e.preventDefault()
|
299 |
+
return
|
300 |
+
}
|
301 |
+
if (!this.isPrepared) {
|
302 |
+
e.preventDefault()
|
303 |
+
this.isPreparing = true
|
304 |
+
fetch(this.previewUrl).then(() => {
|
305 |
+
this.isPreparing = false
|
306 |
+
this.isPrepared = true
|
307 |
+
})
|
308 |
+
}
|
309 |
+
},
|
310 |
+
|
311 |
/**
|
312 |
* Submits first feed step.
|
313 |
*
|
423 |
},
|
424 |
|
425 |
copyToClipboard () {
|
426 |
+
if (this.isCopied) {
|
427 |
+
return
|
|
|
|
|
|
|
|
|
428 |
}
|
429 |
+
copyToClipboard('[wp-rss-aggregator]')
|
430 |
+
this.isCopied = true
|
431 |
+
setTimeout(() => {
|
432 |
+
this.isCopied = false
|
433 |
+
}, 1000)
|
434 |
}
|
435 |
},
|
436 |
components: {
|
js/src/intro/copy.js
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Helper functions to copy text to clipboard.
|
3 |
+
*
|
4 |
+
* @see https://stackoverflow.com/questions/400212/how-do-i-copy-to-the-clipboard-in-javascript
|
5 |
+
*
|
6 |
+
* @param text
|
7 |
+
*/
|
8 |
+
|
9 |
+
const fallbackCopyToClipboard = function (text) {
|
10 |
+
var textArea = document.createElement('textarea')
|
11 |
+
textArea.value = text
|
12 |
+
document.body.appendChild(textArea)
|
13 |
+
textArea.focus()
|
14 |
+
textArea.select()
|
15 |
+
|
16 |
+
try {
|
17 |
+
var successful = document.execCommand('copy')
|
18 |
+
var msg = successful ? 'successful' : 'unsuccessful'
|
19 |
+
console.log('Fallback: Copying text command was ' + msg)
|
20 |
+
} catch (err) {
|
21 |
+
console.error('Fallback: Oops, unable to copy', err)
|
22 |
+
}
|
23 |
+
|
24 |
+
document.body.removeChild(textArea)
|
25 |
+
}
|
26 |
+
|
27 |
+
export function copyToClipboard (text) {
|
28 |
+
if (!navigator.clipboard) {
|
29 |
+
fallbackCopyToClipboard(text)
|
30 |
+
return
|
31 |
+
}
|
32 |
+
navigator.clipboard.writeText(text).then(function () {
|
33 |
+
console.log('Async: Copying to clipboard was successful!')
|
34 |
+
}, function (err) {
|
35 |
+
console.error('Async: Could not copy text: ', err)
|
36 |
+
})
|
37 |
+
}
|
js/src/plugins/Modal.vue
ADDED
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<template>
|
2 |
+
<transition name="modal-transition">
|
3 |
+
<div class="modal" v-if="active" @click.self="$emit('close')">
|
4 |
+
<div :class="['modal__body', this.modalBodyClass]">
|
5 |
+
<div class="modal__header" :class="headerClass">
|
6 |
+
<slot name="header"></slot>
|
7 |
+
</div>
|
8 |
+
<div class="modal__content">
|
9 |
+
<slot name="body"></slot>
|
10 |
+
</div>
|
11 |
+
<div class="modal__footer">
|
12 |
+
<slot name="footer"></slot>
|
13 |
+
</div>
|
14 |
+
</div>
|
15 |
+
</div>
|
16 |
+
</transition>
|
17 |
+
</template>
|
18 |
+
|
19 |
+
<script>
|
20 |
+
/**
|
21 |
+
* Abstract dialog component, solid foundation for
|
22 |
+
* any modals and dialogs that opened over the rest page content.
|
23 |
+
*
|
24 |
+
* @param Vue
|
25 |
+
*/
|
26 |
+
export default {
|
27 |
+
props: {
|
28 |
+
/**
|
29 |
+
* Determines dialog visibility. This property is passed
|
30 |
+
* from outside and cannot be changed inside dialog.
|
31 |
+
* Dialog's consumer is responsible for manipulating dialog's visibility.
|
32 |
+
*
|
33 |
+
* @property {bool}
|
34 |
+
*/
|
35 |
+
active: {
|
36 |
+
type: Boolean
|
37 |
+
},
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Modal title
|
41 |
+
*
|
42 |
+
* @property {string}
|
43 |
+
*/
|
44 |
+
title: {
|
45 |
+
type: String
|
46 |
+
},
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Additional class modifier for modal customization.
|
50 |
+
*
|
51 |
+
* @property {string}
|
52 |
+
*/
|
53 |
+
modalBodyClass: {
|
54 |
+
type: String,
|
55 |
+
default: ''
|
56 |
+
},
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Additional classes for modal header.
|
60 |
+
*
|
61 |
+
* @property {object|Array}
|
62 |
+
*/
|
63 |
+
headerClass: {
|
64 |
+
default () {
|
65 |
+
return {}
|
66 |
+
}
|
67 |
+
},
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Class that applies to the body and used
|
71 |
+
* to prevent body's scroll catch, so long dialog can be scrolled
|
72 |
+
* without interfering with body scroll.
|
73 |
+
*
|
74 |
+
* @property {string}
|
75 |
+
*/
|
76 |
+
dialogOpenedClass: {
|
77 |
+
type: String,
|
78 |
+
default: 'modal-opened'
|
79 |
+
}
|
80 |
+
},
|
81 |
+
|
82 |
+
watch: {
|
83 |
+
/**
|
84 |
+
* Watch for "active" property change and emit corresponding
|
85 |
+
* event when it changed.
|
86 |
+
*
|
87 |
+
* @param isDialogActive {bool}
|
88 |
+
*/
|
89 |
+
active (isDialogActive) {
|
90 |
+
this.$emit(isDialogActive ? 'open' : 'close')
|
91 |
+
}
|
92 |
+
},
|
93 |
+
|
94 |
+
mounted () {
|
95 |
+
/*
|
96 |
+
* Add body "frozen" class to the body when dialog is opened.
|
97 |
+
*/
|
98 |
+
this.$on('open', () => {
|
99 |
+
document.querySelector('body')
|
100 |
+
.classList
|
101 |
+
.add(this.dialogOpenedClass);
|
102 |
+
});
|
103 |
+
|
104 |
+
/*
|
105 |
+
* Remove body "frozen" class from the body when dialog is closed.
|
106 |
+
*/
|
107 |
+
this.$on('close', () => {
|
108 |
+
document.querySelector('body')
|
109 |
+
.classList
|
110 |
+
.remove(this.dialogOpenedClass);
|
111 |
+
});
|
112 |
+
},
|
113 |
+
}
|
114 |
+
</script>
|
js/src/plugins/PluginDisablePoll.vue
ADDED
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<template>
|
2 |
+
<div class="wpra-plugin-disable-poll">
|
3 |
+
<modal :active="isModalVisible"
|
4 |
+
@close="closeModal"
|
5 |
+
:header-class="'invisible-header'"
|
6 |
+
>
|
7 |
+
<div slot="header">
|
8 |
+
<div class="wpra-plugin-disable-poll__logo">
|
9 |
+
<img :src="image('light-line-logo.png')" alt="">
|
10 |
+
</div>
|
11 |
+
<h3>
|
12 |
+
Do you have a moment to share why you are deactivating WP RSS Aggregator?
|
13 |
+
</h3>
|
14 |
+
<p>
|
15 |
+
Your feedback will help us to improve our plugins and service.
|
16 |
+
</p>
|
17 |
+
</div>
|
18 |
+
|
19 |
+
<div slot="body">
|
20 |
+
<SerializedForm :form="form" v-model="model"/>
|
21 |
+
</div>
|
22 |
+
|
23 |
+
<div slot="footer">
|
24 |
+
<div class="footer-confirm__buttons">
|
25 |
+
<button class="button button-clear" @click="deactivate">
|
26 |
+
Skip & Deactivate
|
27 |
+
</button>
|
28 |
+
<button class="button button-primary"
|
29 |
+
:class="{'loading-button': isDeactivating}"
|
30 |
+
@click="submit">
|
31 |
+
Submit & Deactivate
|
32 |
+
</button>
|
33 |
+
</div>
|
34 |
+
</div>
|
35 |
+
</modal>
|
36 |
+
</div>
|
37 |
+
</template>
|
38 |
+
|
39 |
+
<script>
|
40 |
+
import Modal from './Modal'
|
41 |
+
import SerializedForm from './SerializedForm'
|
42 |
+
import axios from 'axios'
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Selector string for plugin's deactivation link.
|
46 |
+
*
|
47 |
+
* @type {string}
|
48 |
+
*/
|
49 |
+
const deactivateSelector = '[data-slug="wp-rss-aggregator"] .deactivate a'
|
50 |
+
const deactivateLink = document.querySelector(deactivateSelector)
|
51 |
+
|
52 |
+
export default {
|
53 |
+
components: {
|
54 |
+
Modal,
|
55 |
+
SerializedForm,
|
56 |
+
},
|
57 |
+
data () {
|
58 |
+
return {
|
59 |
+
isDeactivating: false,
|
60 |
+
deactivateUrl: null,
|
61 |
+
submitUrl: WrpaDisablePoll.url,
|
62 |
+
model: WrpaDisablePoll.model,
|
63 |
+
form: WrpaDisablePoll.form,
|
64 |
+
isModalVisible: false
|
65 |
+
}
|
66 |
+
},
|
67 |
+
watch: {
|
68 |
+
'model.reason' () {
|
69 |
+
this.model.follow_up = null
|
70 |
+
}
|
71 |
+
},
|
72 |
+
mounted () {
|
73 |
+
deactivateLink.addEventListener('click', this.handleDeactivateClick)
|
74 |
+
},
|
75 |
+
methods: {
|
76 |
+
image (path) {
|
77 |
+
return WrpaDisablePoll.image + path
|
78 |
+
},
|
79 |
+
|
80 |
+
handleDeactivateClick (e) {
|
81 |
+
if (this.isModalVisible) {
|
82 |
+
return
|
83 |
+
}
|
84 |
+
|
85 |
+
e.preventDefault()
|
86 |
+
this.isModalVisible = true
|
87 |
+
},
|
88 |
+
|
89 |
+
closeModal () {
|
90 |
+
this.isModalVisible = false
|
91 |
+
this.deactivateUrl = null
|
92 |
+
},
|
93 |
+
|
94 |
+
submit () {
|
95 |
+
this.isDeactivating = true
|
96 |
+
axios.post(this.submitUrl, this.model, {
|
97 |
+
headers: {
|
98 |
+
'Content-Type': 'application/x-www-form-urlencoded'
|
99 |
+
}
|
100 |
+
}).then(() => {
|
101 |
+
this.deactivate()
|
102 |
+
}).finally(() => {
|
103 |
+
this.isDeactivating = false
|
104 |
+
})
|
105 |
+
},
|
106 |
+
|
107 |
+
deactivate () {
|
108 |
+
deactivateLink.click()
|
109 |
+
}
|
110 |
+
}
|
111 |
+
}
|
112 |
+
</script>
|
js/src/plugins/SerializedForm.vue
ADDED
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<template>
|
2 |
+
<div class="form">
|
3 |
+
<div class="form-group"
|
4 |
+
v-for="datum of form"
|
5 |
+
v-if="satisfiesCondition(datum)"
|
6 |
+
>
|
7 |
+
<template v-if="datum.type === 'radio'">
|
8 |
+
<label :for="datum.name" v-html="datum.label" v-if="datum.label"></label>
|
9 |
+
<div class="form-check" v-for="(radio, $i) of datum.options">
|
10 |
+
<input type="radio"
|
11 |
+
:name="datum.name"
|
12 |
+
:id="datum.name + '_' + $i"
|
13 |
+
:value="radio.value"
|
14 |
+
v-model="model[datum.name]"
|
15 |
+
>
|
16 |
+
<label :for="datum.name + '_' + $i">
|
17 |
+
{{ radio.label || radio.value }}
|
18 |
+
</label>
|
19 |
+
</div>
|
20 |
+
</template>
|
21 |
+
|
22 |
+
<template v-if="datum.type === 'textarea'">
|
23 |
+
<label :for="datum.name" v-html="datum.label" v-if="datum.label"></label>
|
24 |
+
<textarea v-model="model[datum.name]" :id="datum.name"></textarea>
|
25 |
+
</template>
|
26 |
+
|
27 |
+
<template v-if="datum.type === 'content'">
|
28 |
+
<div :class="datum.className">
|
29 |
+
<p v-html="datum.label"></p>
|
30 |
+
</div>
|
31 |
+
</template>
|
32 |
+
</div>
|
33 |
+
</div>
|
34 |
+
</template>
|
35 |
+
|
36 |
+
<script>
|
37 |
+
export default {
|
38 |
+
props: {
|
39 |
+
/*
|
40 |
+
* Form, described by object containing information
|
41 |
+
* about each field.
|
42 |
+
*/
|
43 |
+
form: {
|
44 |
+
type: Array,
|
45 |
+
},
|
46 |
+
|
47 |
+
/*
|
48 |
+
* Form model.
|
49 |
+
*/
|
50 |
+
value: {
|
51 |
+
type: Object,
|
52 |
+
}
|
53 |
+
},
|
54 |
+
computed: {
|
55 |
+
model: {
|
56 |
+
get () {
|
57 |
+
return this.value
|
58 |
+
},
|
59 |
+
set (value) {
|
60 |
+
this.$emit('input', value)
|
61 |
+
}
|
62 |
+
}
|
63 |
+
},
|
64 |
+
methods: {
|
65 |
+
satisfiesCondition (datum) {
|
66 |
+
if (!datum.condition) {
|
67 |
+
return true
|
68 |
+
}
|
69 |
+
let compareFunction = this.getConditionFunction(datum.condition.operator);
|
70 |
+
if (!compareFunction) {
|
71 |
+
return false
|
72 |
+
}
|
73 |
+
return compareFunction(datum.condition.field, datum.condition.value)
|
74 |
+
},
|
75 |
+
|
76 |
+
getConditionFunction (operator) {
|
77 |
+
const fns = {
|
78 |
+
'=': (field, value) => {
|
79 |
+
return this.model[field] === value
|
80 |
+
}
|
81 |
+
}
|
82 |
+
if (!fns[operator]) {
|
83 |
+
return null
|
84 |
+
}
|
85 |
+
return fns[operator]
|
86 |
+
}
|
87 |
+
}
|
88 |
+
}
|
89 |
+
</script>
|
js/src/plugins/index.js
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
require('./../../../css/src/plugins/index.scss')
|
2 |
+
|
3 |
+
import Vue from 'vue'
|
4 |
+
import PluginDisablePoll from './PluginDisablePoll'
|
5 |
+
|
6 |
+
new Vue({
|
7 |
+
el: '#wpra-plugins-app',
|
8 |
+
template: '<PluginDisablePoll/>',
|
9 |
+
components: { PluginDisablePoll }
|
10 |
+
})
|
js/update.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
!function(e,o){"object"==typeof exports&&"object"==typeof module?module.exports=o():"function"==typeof define&&define.amd?define([],o):"object"==typeof exports?exports.WPRA=o():e.WPRA=o()}("undefined"!=typeof self?self:this,function(){return webpackJsonpWPRA([3],{37:function(e,o){}},[37])});
|
js/wpra-manifest.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
!function(r){function n(e){if(o[e])return o[e].exports;var t=o[e]={i:e,l:!1,exports:{}};return r[e].call(t.exports,t,t.exports,n),t.l=!0,t.exports}var e=window.webpackJsonpWPRA;window.webpackJsonpWPRA=function(o,u,c){for(var f,i,p,a=0,l=[];a<o.length;a++)i=o[a],t[i]&&l.push(t[i][0]),t[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(e&&e(o,u,c);l.length;)l.shift()();if(c)for(a=0;a<c.length;a++)p=n(n.s=c[a]);return p};var o={},t={4:0};n.m=r,n.c=o,n.d=function(r,e,o){n.o(r,e)||Object.defineProperty(r,e,{configurable:!1,enumerable:!0,get:o})},n.n=function(r){var e=r&&r.__esModule?function(){return r.default}:function(){return r};return n.d(e,"a",e),e},n.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},n.p="",n.oe=function(r){throw console.error(r),r}}([]);
|
js/wpra-vendor.min.js
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
webpackJsonpWPRA([0],[function(e,t,n){"use strict";function r(e){return"[object Array]"===A.call(e)}function o(e){return"[object ArrayBuffer]"===A.call(e)}function i(e){return"undefined"!=typeof FormData&&e instanceof FormData}function a(e){return"undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&e.buffer instanceof ArrayBuffer}function s(e){return"string"==typeof e}function c(e){return"number"==typeof e}function u(e){return void 0===e}function f(e){return null!==e&&"object"==typeof e}function l(e){return"[object Date]"===A.call(e)}function p(e){return"[object File]"===A.call(e)}function d(e){return"[object Blob]"===A.call(e)}function v(e){return"[object Function]"===A.call(e)}function h(e){return f(e)&&v(e.pipe)}function m(e){return"undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams}function y(e){return e.replace(/^\s*/,"").replace(/\s*$/,"")}function g(){return("undefined"==typeof navigator||"ReactNative"!==navigator.product)&&"undefined"!=typeof window&&"undefined"!=typeof document}function b(e,t){if(null!==e&&void 0!==e)if("object"!=typeof e&&(e=[e]),r(e))for(var n=0,o=e.length;n<o;n++)t.call(null,e[n],n,e);else for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&t.call(null,e[i],i,e)}function _(){function e(e,n){"object"==typeof t[n]&&"object"==typeof e?t[n]=_(t[n],e):t[n]=e}for(var t={},n=0,r=arguments.length;n<r;n++)b(arguments[n],e);return t}function w(e,t,n){return b(t,function(t,r){e[r]=n&&"function"==typeof t?x(t,n):t}),e}var x=n(6),$=n(20),A=Object.prototype.toString;e.exports={isArray:r,isArrayBuffer:o,isBuffer:$,isFormData:i,isArrayBufferView:a,isString:s,isNumber:c,isObject:f,isUndefined:u,isDate:l,isFile:p,isBlob:d,isFunction:v,isStream:h,isURLSearchParams:m,isStandardBrowserEnv:g,forEach:b,merge:_,extend:w,trim:y}},function(e,t,n){"use strict";function r(e,t,n,r,o,i,a,s){var c="function"==typeof e?e.options:e;t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),r&&(c.functional=!0),i&&(c._scopeId="data-v-"+i);var u;if(a?(u=function(e){e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,e||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),o&&o.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(a)},c._ssrRegister=u):o&&(u=s?function(){o.call(this,this.$root.$options.shadowRoot)}:o),u)if(c.functional){c._injectStyles=u;var f=c.render;c.render=function(e,t){return u.call(t),f(e,t)}}else{var l=c.beforeCreate;c.beforeCreate=l?[].concat(l,u):[u]}return{exports:e,options:c}}t.a=r},function(e,t){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";(function(t){function r(e,t){!o.isUndefined(e)&&o.isUndefined(e["Content-Type"])&&(e["Content-Type"]=t)}var o=n(0),i=n(22),a={"Content-Type":"application/x-www-form-urlencoded"},s={adapter:function(){var e;return"undefined"!=typeof XMLHttpRequest?e=n(7):void 0!==t&&(e=n(7)),e}(),transformRequest:[function(e,t){return i(t,"Content-Type"),o.isFormData(e)||o.isArrayBuffer(e)||o.isBuffer(e)||o.isStream(e)||o.isFile(e)||o.isBlob(e)?e:o.isArrayBufferView(e)?e.buffer:o.isURLSearchParams(e)?(r(t,"application/x-www-form-urlencoded;charset=utf-8"),e.toString()):o.isObject(e)?(r(t,"application/json;charset=utf-8"),JSON.stringify(e)):e}],transformResponse:[function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(e){}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,validateStatus:function(e){return e>=200&&e<300}};s.headers={common:{Accept:"application/json, text/plain, */*"}},o.forEach(["delete","get","head"],function(e){s.headers[e]={}}),o.forEach(["post","put","patch"],function(e){s.headers[e]=o.merge(a)}),e.exports=s}).call(t,n(5))},function(e,t,n){"use strict";(function(e,n){function r(e){return void 0===e||null===e}function o(e){return void 0!==e&&null!==e}function i(e){return!0===e}function a(e){return!1===e}function s(e){return"string"==typeof e||"number"==typeof e||"symbol"==typeof e||"boolean"==typeof e}function c(e){return null!==e&&"object"==typeof e}function u(e){return"[object Object]"===Ci.call(e)}function f(e){return"[object RegExp]"===Ci.call(e)}function l(e){var t=parseFloat(String(e));return t>=0&&Math.floor(t)===t&&isFinite(e)}function p(e){return o(e)&&"function"==typeof e.then&&"function"==typeof e.catch}function d(e){return null==e?"":Array.isArray(e)||u(e)&&e.toString===Ci?JSON.stringify(e,null,2):String(e)}function v(e){var t=parseFloat(e);return isNaN(t)?e:t}function h(e,t){for(var n=Object.create(null),r=e.split(","),o=0;o<r.length;o++)n[r[o]]=!0;return t?function(e){return n[e.toLowerCase()]}:function(e){return n[e]}}function m(e,t){if(e.length){var n=e.indexOf(t);if(n>-1)return e.splice(n,1)}}function y(e,t){return Si.call(e,t)}function g(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}}function b(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n}function _(e,t){return e.bind(t)}function w(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function x(e,t){for(var n in t)e[n]=t[n];return e}function $(e){for(var t={},n=0;n<e.length;n++)e[n]&&x(t,e[n]);return t}function A(e,t,n){}function C(e,t){if(e===t)return!0;var n=c(e),r=c(t);if(!n||!r)return!n&&!r&&String(e)===String(t);try{var o=Array.isArray(e),i=Array.isArray(t);if(o&&i)return e.length===t.length&&e.every(function(e,n){return C(e,t[n])});if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(o||i)return!1;var a=Object.keys(e),s=Object.keys(t);return a.length===s.length&&a.every(function(n){return C(e[n],t[n])})}catch(e){return!1}}function k(e,t){for(var n=0;n<e.length;n++)if(C(e[n],t))return n;return-1}function T(e){var t=!1;return function(){t||(t=!0,e.apply(this,arguments))}}function S(e){var t=(e+"").charCodeAt(0);return 36===t||95===t}function O(e,t,n,r){Object.defineProperty(e,t,{value:n,enumerable:!!r,writable:!0,configurable:!0})}function E(e){if(!Hi.test(e)){var t=e.split(".");return function(e){for(var n=0;n<t.length;n++){if(!e)return;e=e[t[n]]}return e}}}function j(e){return"function"==typeof e&&/native code/.test(e.toString())}function I(e){fa.push(e),ua.target=e}function L(){fa.pop(),ua.target=fa[fa.length-1]}function N(e){return new la(void 0,void 0,void 0,String(e))}function D(e){var t=new la(e.tag,e.data,e.children&&e.children.slice(),e.text,e.elm,e.context,e.componentOptions,e.asyncFactory);return t.ns=e.ns,t.isStatic=e.isStatic,t.key=e.key,t.isComment=e.isComment,t.fnContext=e.fnContext,t.fnOptions=e.fnOptions,t.fnScopeId=e.fnScopeId,t.asyncMeta=e.asyncMeta,t.isCloned=!0,t}function P(e){ya=e}function R(e,t){e.__proto__=t}function M(e,t,n){for(var r=0,o=n.length;r<o;r++){var i=n[r];O(e,i,t[i])}}function B(e,t){if(c(e)&&!(e instanceof la)){var n;return y(e,"__ob__")&&e.__ob__ instanceof ga?n=e.__ob__:ya&&!oa()&&(Array.isArray(e)||u(e))&&Object.isExtensible(e)&&!e._isVue&&(n=new ga(e)),t&&n&&n.vmCount++,n}}function F(e,t,n,r,o){var i=new ua,a=Object.getOwnPropertyDescriptor(e,t);if(!a||!1!==a.configurable){var s=a&&a.get,c=a&&a.set;s&&!c||2!==arguments.length||(n=e[t]);var u=!o&&B(n);Object.defineProperty(e,t,{enumerable:!0,configurable:!0,get:function(){var t=s?s.call(e):n;return ua.target&&(i.depend(),u&&(u.dep.depend(),Array.isArray(t)&&q(t))),t},set:function(t){var r=s?s.call(e):n;t===r||t!==t&&r!==r||s&&!c||(c?c.call(e,t):n=t,u=!o&&B(t),i.notify())}})}}function U(e,t,n){if(Array.isArray(e)&&l(t))return e.length=Math.max(e.length,t),e.splice(t,1,n),n;if(t in e&&!(t in Object.prototype))return e[t]=n,n;var r=e.__ob__;return e._isVue||r&&r.vmCount?n:r?(F(r.value,t,n),r.dep.notify(),n):(e[t]=n,n)}function H(e,t){if(Array.isArray(e)&&l(t))return void e.splice(t,1);var n=e.__ob__;e._isVue||n&&n.vmCount||y(e,t)&&(delete e[t],n&&n.dep.notify())}function q(e){for(var t=void 0,n=0,r=e.length;n<r;n++)t=e[n],t&&t.__ob__&&t.__ob__.dep.depend(),Array.isArray(t)&&q(t)}function z(e,t){if(!t)return e;for(var n,r,o,i=aa?Reflect.ownKeys(t):Object.keys(t),a=0;a<i.length;a++)"__ob__"!==(n=i[a])&&(r=e[n],o=t[n],y(e,n)?r!==o&&u(r)&&u(o)&&z(r,o):U(e,n,o));return e}function V(e,t,n){return n?function(){var r="function"==typeof t?t.call(n,n):t,o="function"==typeof e?e.call(n,n):e;return r?z(r,o):o}:t?e?function(){return z("function"==typeof t?t.call(this,this):t,"function"==typeof e?e.call(this,this):e)}:t:e}function K(e,t){var n=t?e?e.concat(t):Array.isArray(t)?t:[t]:e;return n?J(n):n}function J(e){for(var t=[],n=0;n<e.length;n++)-1===t.indexOf(e[n])&&t.push(e[n]);return t}function X(e,t,n,r){var o=Object.create(e||null);return t?x(o,t):o}function W(e,t){var n=e.props;if(n){var r,o,i,a={};if(Array.isArray(n))for(r=n.length;r--;)"string"==typeof(o=n[r])&&(i=Ei(o),a[i]={type:null});else if(u(n))for(var s in n)o=n[s],i=Ei(s),a[i]=u(o)?o:{type:o};e.props=a}}function G(e,t){var n=e.inject;if(n){var r=e.inject={};if(Array.isArray(n))for(var o=0;o<n.length;o++)r[n[o]]={from:n[o]};else if(u(n))for(var i in n){var a=n[i];r[i]=u(a)?x({from:i},a):{from:a}}}}function Z(e){var t=e.directives;if(t)for(var n in t){var r=t[n];"function"==typeof r&&(t[n]={bind:r,update:r})}}function Y(e,t,n){function r(r){var o=ba[r]||wa;s[r]=o(e[r],t[r],n,r)}if("function"==typeof t&&(t=t.options),W(t,n),G(t,n),Z(t),!t._base&&(t.extends&&(e=Y(e,t.extends,n)),t.mixins))for(var o=0,i=t.mixins.length;o<i;o++)e=Y(e,t.mixins[o],n);var a,s={};for(a in e)r(a);for(a in t)y(e,a)||r(a);return s}function Q(e,t,n,r){if("string"==typeof n){var o=e[t];if(y(o,n))return o[n];var i=Ei(n);if(y(o,i))return o[i];var a=ji(i);return y(o,a)?o[a]:o[n]||o[i]||o[a]}}function ee(e,t,n,r){var o=t[e],i=!y(n,e),a=n[e],s=oe(Boolean,o.type);if(s>-1)if(i&&!y(o,"default"))a=!1;else if(""===a||a===Li(e)){var c=oe(String,o.type);(c<0||s<c)&&(a=!0)}if(void 0===a){a=te(r,o,e);var u=ya;P(!0),B(a),P(u)}return a}function te(e,t,n){if(y(t,"default")){var r=t.default;return e&&e.$options.propsData&&void 0===e.$options.propsData[n]&&void 0!==e._props[n]?e._props[n]:"function"==typeof r&&"Function"!==ne(t.type)?r.call(e):r}}function ne(e){var t=e&&e.toString().match(/^\s*function (\w+)/);return t?t[1]:""}function re(e,t){return ne(e)===ne(t)}function oe(e,t){if(!Array.isArray(t))return re(t,e)?0:-1;for(var n=0,r=t.length;n<r;n++)if(re(t[n],e))return n;return-1}function ie(e,t,n){I();try{if(t)for(var r=t;r=r.$parent;){var o=r.$options.errorCaptured;if(o)for(var i=0;i<o.length;i++)try{var a=!1===o[i].call(r,e,t,n);if(a)return}catch(e){se(e,r,"errorCaptured hook")}}se(e,t,n)}finally{L()}}function ae(e,t,n,r,o){var i;try{(i=n?e.apply(t,n):e.call(t))&&!i._isVue&&p(i)&&(i=i.catch(function(e){return ie(e,r,o+" (Promise/async)")}))}catch(e){ie(e,r,o)}return i}function se(e,t,n){if(Fi.errorHandler)try{return Fi.errorHandler.call(null,e,t,n)}catch(t){t!==e&&ce(t,null,"config.errorHandler")}ce(e,t,n)}function ce(e,t,n){if(!zi&&!Vi||"undefined"==typeof console)throw e;console.error(e)}function ue(){Aa=!1;var e=$a.slice(0);$a.length=0;for(var t=0;t<e.length;t++)e[t]()}function fe(e,t){var n;if($a.push(function(){if(e)try{e.call(t)}catch(e){ie(e,t,"nextTick")}else n&&n(t)}),Aa||(Aa=!0,_a()),!e&&"undefined"!=typeof Promise)return new Promise(function(e){n=e})}function le(e){pe(e,Oa),Oa.clear()}function pe(e,t){var n,r,o=Array.isArray(e);if(!(!o&&!c(e)||Object.isFrozen(e)||e instanceof la)){if(e.__ob__){var i=e.__ob__.dep.id;if(t.has(i))return;t.add(i)}if(o)for(n=e.length;n--;)pe(e[n],t);else for(r=Object.keys(e),n=r.length;n--;)pe(e[r[n]],t)}}function de(e,t){function n(){var e=arguments,r=n.fns;if(!Array.isArray(r))return ae(r,null,arguments,t,"v-on handler");for(var o=r.slice(),i=0;i<o.length;i++)ae(o[i],null,e,t,"v-on handler")}return n.fns=e,n}function ve(e,t,n,o,a,s){var c,u,f,l;for(c in e)u=e[c],f=t[c],l=Ea(c),r(u)||(r(f)?(r(u.fns)&&(u=e[c]=de(u,s)),i(l.once)&&(u=e[c]=a(l.name,u,l.capture)),n(l.name,u,l.capture,l.passive,l.params)):u!==f&&(f.fns=u,e[c]=f));for(c in t)r(e[c])&&(l=Ea(c),o(l.name,t[c],l.capture))}function he(e,t,n){function a(){n.apply(this,arguments),m(s.fns,a)}e instanceof la&&(e=e.data.hook||(e.data.hook={}));var s,c=e[t];r(c)?s=de([a]):o(c.fns)&&i(c.merged)?(s=c,s.fns.push(a)):s=de([c,a]),s.merged=!0,e[t]=s}function me(e,t,n){var i=t.options.props;if(!r(i)){var a={},s=e.attrs,c=e.props;if(o(s)||o(c))for(var u in i){var f=Li(u);ye(a,c,u,f,!0)||ye(a,s,u,f,!1)}return a}}function ye(e,t,n,r,i){if(o(t)){if(y(t,n))return e[n]=t[n],i||delete t[n],!0;if(y(t,r))return e[n]=t[r],i||delete t[r],!0}return!1}function ge(e){for(var t=0;t<e.length;t++)if(Array.isArray(e[t]))return Array.prototype.concat.apply([],e);return e}function be(e){return s(e)?[N(e)]:Array.isArray(e)?we(e):void 0}function _e(e){return o(e)&&o(e.text)&&a(e.isComment)}function we(e,t){var n,a,c,u,f=[];for(n=0;n<e.length;n++)a=e[n],r(a)||"boolean"==typeof a||(c=f.length-1,u=f[c],Array.isArray(a)?a.length>0&&(a=we(a,(t||"")+"_"+n),_e(a[0])&&_e(u)&&(f[c]=N(u.text+a[0].text),a.shift()),f.push.apply(f,a)):s(a)?_e(u)?f[c]=N(u.text+a):""!==a&&f.push(N(a)):_e(a)&&_e(u)?f[c]=N(u.text+a.text):(i(e._isVList)&&o(a.tag)&&r(a.key)&&o(t)&&(a.key="__vlist"+t+"_"+n+"__"),f.push(a)));return f}function xe(e){var t=e.$options.provide;t&&(e._provided="function"==typeof t?t.call(e):t)}function $e(e){var t=Ae(e.$options.inject,e);t&&(P(!1),Object.keys(t).forEach(function(n){F(e,n,t[n])}),P(!0))}function Ae(e,t){if(e){for(var n=Object.create(null),r=aa?Reflect.ownKeys(e):Object.keys(e),o=0;o<r.length;o++){var i=r[o];if("__ob__"!==i){for(var a=e[i].from,s=t;s;){if(s._provided&&y(s._provided,a)){n[i]=s._provided[a];break}s=s.$parent}if(!s&&"default"in e[i]){var c=e[i].default;n[i]="function"==typeof c?c.call(t):c}}}return n}}function Ce(e,t){if(!e||!e.length)return{};for(var n={},r=0,o=e.length;r<o;r++){var i=e[r],a=i.data;if(a&&a.attrs&&a.attrs.slot&&delete a.attrs.slot,i.context!==t&&i.fnContext!==t||!a||null==a.slot)(n.default||(n.default=[])).push(i);else{var s=a.slot,c=n[s]||(n[s]=[]);"template"===i.tag?c.push.apply(c,i.children||[]):c.push(i)}}for(var u in n)n[u].every(ke)&&delete n[u];return n}function ke(e){return e.isComment&&!e.asyncFactory||" "===e.text}function Te(e,t,n){var r,o=!e||!!e.$stable,i=e&&e.$key;if(e){if(e._normalized)return e._normalized;if(o&&n&&n!==Ai&&i===n.$key&&0===Object.keys(t).length)return n;r={};for(var a in e)e[a]&&"$"!==a[0]&&(r[a]=Se(t,a,e[a]))}else r={};for(var s in t)s in r||(r[s]=Oe(t,s));return e&&Object.isExtensible(e)&&(e._normalized=r),O(r,"$stable",o),O(r,"$key",i),r}function Se(e,t,n){var r=function(){var e=arguments.length?n.apply(null,arguments):n({});return e=e&&"object"==typeof e&&!Array.isArray(e)?[e]:be(e),e&&0===e.length?void 0:e};return n.proxy&&Object.defineProperty(e,t,{get:r,enumerable:!0,configurable:!0}),r}function Oe(e,t){return function(){return e[t]}}function Ee(e,t){var n,r,i,a,s;if(Array.isArray(e)||"string"==typeof e)for(n=new Array(e.length),r=0,i=e.length;r<i;r++)n[r]=t(e[r],r);else if("number"==typeof e)for(n=new Array(e),r=0;r<e;r++)n[r]=t(r+1,r);else if(c(e))if(aa&&e[Symbol.iterator]){n=[];for(var u=e[Symbol.iterator](),f=u.next();!f.done;)n.push(t(f.value,n.length)),f=u.next()}else for(a=Object.keys(e),n=new Array(a.length),r=0,i=a.length;r<i;r++)s=a[r],n[r]=t(e[s],s,r);return o(n)||(n=[]),n._isVList=!0,n}function je(e,t,n,r){var o,i=this.$scopedSlots[e];i?(n=n||{},r&&(n=x(x({},r),n)),o=i(n)||t):o=this.$slots[e]||t;var a=n&&n.slot;return a?this.$createElement("template",{slot:a},o):o}function Ie(e){return Q(this.$options,"filters",e,!0)||Pi}function Le(e,t){return Array.isArray(e)?-1===e.indexOf(t):e!==t}function Ne(e,t,n,r,o){var i=Fi.keyCodes[t]||n;return o&&r&&!Fi.keyCodes[t]?Le(o,r):i?Le(i,e):r?Li(r)!==t:void 0}function De(e,t,n,r,o){if(n&&c(n)){Array.isArray(n)&&(n=$(n));var i;for(var a in n)!function(a){if("class"===a||"style"===a||Ti(a))i=e;else{var s=e.attrs&&e.attrs.type;i=r||Fi.mustUseProp(t,s,a)?e.domProps||(e.domProps={}):e.attrs||(e.attrs={})}var c=Ei(a);a in i||c in i||(i[a]=n[a],!o)||((e.on||(e.on={}))["update:"+c]=function(e){n[a]=e})}(a)}return e}function Pe(e,t){var n=this._staticTrees||(this._staticTrees=[]),r=n[e];return r&&!t?r:(r=n[e]=this.$options.staticRenderFns[e].call(this._renderProxy,null,this),Me(r,"__static__"+e,!1),r)}function Re(e,t,n){return Me(e,"__once__"+t+(n?"_"+n:""),!0),e}function Me(e,t,n){if(Array.isArray(e))for(var r=0;r<e.length;r++)e[r]&&"string"!=typeof e[r]&&Be(e[r],t+"_"+r,n);else Be(e,t,n)}function Be(e,t,n){e.isStatic=!0,e.key=t,e.isOnce=n}function Fe(e,t){if(t&&u(t)){var n=e.on=e.on?x({},e.on):{};for(var r in t){var o=n[r],i=t[r];n[r]=o?[].concat(o,i):i}}return e}function Ue(e,t,n,r){t=t||{$stable:!n};for(var o=0;o<e.length;o++){var i=e[o];Array.isArray(i)?Ue(i,t,n):i&&(i.proxy&&(i.fn.proxy=!0),t[i.key]=i.fn)}return r&&(t.$key=r),t}function He(e,t){for(var n=0;n<t.length;n+=2){var r=t[n];"string"==typeof r&&r&&(e[t[n]]=t[n+1])}return e}function qe(e,t){return"string"==typeof e?t+e:e}function ze(e){e._o=Re,e._n=v,e._s=d,e._l=Ee,e._t=je,e._q=C,e._i=k,e._m=Pe,e._f=Ie,e._k=Ne,e._b=De,e._v=N,e._e=da,e._u=Ue,e._g=Fe,e._d=He,e._p=qe}function Ve(e,t,n,r,o){var a,s=this,c=o.options;y(r,"_uid")?(a=Object.create(r),a._original=r):(a=r,r=r._original);var u=i(c._compiled),f=!u;this.data=e,this.props=t,this.children=n,this.parent=r,this.listeners=e.on||Ai,this.injections=Ae(c.inject,r),this.slots=function(){return s.$slots||Te(e.scopedSlots,s.$slots=Ce(n,r)),s.$slots},Object.defineProperty(this,"scopedSlots",{enumerable:!0,get:function(){return Te(e.scopedSlots,this.slots())}}),u&&(this.$options=c,this.$slots=this.slots(),this.$scopedSlots=Te(e.scopedSlots,this.$slots)),c._scopeId?this._c=function(e,t,n,o){var i=et(a,e,t,n,o,f);return i&&!Array.isArray(i)&&(i.fnScopeId=c._scopeId,i.fnContext=r),i}:this._c=function(e,t,n,r){return et(a,e,t,n,r,f)}}function Ke(e,t,n,r,i){var a=e.options,s={},c=a.props;if(o(c))for(var u in c)s[u]=ee(u,c,t||Ai);else o(n.attrs)&&Xe(s,n.attrs),o(n.props)&&Xe(s,n.props);var f=new Ve(n,s,i,r,e),l=a.render.call(null,f._c,f);if(l instanceof la)return Je(l,n,f.parent,a,f);if(Array.isArray(l)){for(var p=be(l)||[],d=new Array(p.length),v=0;v<p.length;v++)d[v]=Je(p[v],n,f.parent,a,f);return d}}function Je(e,t,n,r,o){var i=D(e);return i.fnContext=n,i.fnOptions=r,t.slot&&((i.data||(i.data={})).slot=t.slot),i}function Xe(e,t){for(var n in t)e[Ei(n)]=t[n]}function We(e,t,n,a,s){if(!r(e)){var u=n.$options._base;if(c(e)&&(e=u.extend(e)),"function"==typeof e){var f;if(r(e.cid)&&(f=e,void 0===(e=st(f,u))))return at(f,t,n,a,s);t=t||{},Ht(e),o(t.model)&&Qe(e.options,t);var l=me(t,e,s);if(i(e.options.functional))return Ke(e,l,t,n,a);var p=t.on;if(t.on=t.nativeOn,i(e.options.abstract)){var d=t.slot;t={},d&&(t.slot=d)}Ze(t);var v=e.options.name||s;return new la("vue-component-"+e.cid+(v?"-"+v:""),t,void 0,void 0,void 0,n,{Ctor:e,propsData:l,listeners:p,tag:s,children:a},f)}}}function Ge(e,t){var n={_isComponent:!0,_parentVnode:e,parent:t},r=e.data.inlineTemplate;return o(r)&&(n.render=r.render,n.staticRenderFns=r.staticRenderFns),new e.componentOptions.Ctor(n)}function Ze(e){for(var t=e.hook||(e.hook={}),n=0;n<La.length;n++){var r=La[n],o=t[r],i=Ia[r];o===i||o&&o._merged||(t[r]=o?Ye(i,o):i)}}function Ye(e,t){var n=function(n,r){e(n,r),t(n,r)};return n._merged=!0,n}function Qe(e,t){var n=e.model&&e.model.prop||"value",r=e.model&&e.model.event||"input";(t.attrs||(t.attrs={}))[n]=t.model.value;var i=t.on||(t.on={}),a=i[r],s=t.model.callback;o(a)?(Array.isArray(a)?-1===a.indexOf(s):a!==s)&&(i[r]=[s].concat(a)):i[r]=s}function et(e,t,n,r,o,a){return(Array.isArray(n)||s(n))&&(o=r,r=n,n=void 0),i(a)&&(o=Da),tt(e,t,n,r,o)}function tt(e,t,n,r,i){if(o(n)&&o(n.__ob__))return da();if(o(n)&&o(n.is)&&(t=n.is),!t)return da();Array.isArray(r)&&"function"==typeof r[0]&&(n=n||{},n.scopedSlots={default:r[0]},r.length=0),i===Da?r=be(r):i===Na&&(r=ge(r));var a,s;if("string"==typeof t){var c;s=e.$vnode&&e.$vnode.ns||Fi.getTagNamespace(t),a=Fi.isReservedTag(t)?new la(Fi.parsePlatformTagName(t),n,r,void 0,void 0,e):n&&n.pre||!o(c=Q(e.$options,"components",t))?new la(t,n,r,void 0,void 0,e):We(c,n,e,r,t)}else a=We(t,n,e,r);return Array.isArray(a)?a:o(a)?(o(s)&&nt(a,s),o(n)&&rt(n),a):da()}function nt(e,t,n){if(e.ns=t,"foreignObject"===e.tag&&(t=void 0,n=!0),o(e.children))for(var a=0,s=e.children.length;a<s;a++){var c=e.children[a];o(c.tag)&&(r(c.ns)||i(n)&&"svg"!==c.tag)&&nt(c,t,n)}}function rt(e){c(e.style)&&le(e.style),c(e.class)&&le(e.class)}function ot(e){e._vnode=null,e._staticTrees=null;var t=e.$options,n=e.$vnode=t._parentVnode,r=n&&n.context;e.$slots=Ce(t._renderChildren,r),e.$scopedSlots=Ai,e._c=function(t,n,r,o){return et(e,t,n,r,o,!1)},e.$createElement=function(t,n,r,o){return et(e,t,n,r,o,!0)};var o=n&&n.data;F(e,"$attrs",o&&o.attrs||Ai,null,!0),F(e,"$listeners",t._parentListeners||Ai,null,!0)}function it(e,t){return(e.__esModule||aa&&"Module"===e[Symbol.toStringTag])&&(e=e.default),c(e)?t.extend(e):e}function at(e,t,n,r,o){var i=da();return i.asyncFactory=e,i.asyncMeta={data:t,context:n,children:r,tag:o},i}function st(e,t){if(i(e.error)&&o(e.errorComp))return e.errorComp;if(o(e.resolved))return e.resolved;if(i(e.loading)&&o(e.loadingComp))return e.loadingComp;var n=Pa;if(!o(e.owners)){var a=e.owners=[n],s=!0,u=function(e){for(var t=0,n=a.length;t<n;t++)a[t].$forceUpdate();e&&(a.length=0)},f=T(function(n){e.resolved=it(n,t),s?a.length=0:u(!0)}),l=T(function(t){o(e.errorComp)&&(e.error=!0,u(!0))}),d=e(f,l);return c(d)&&(p(d)?r(e.resolved)&&d.then(f,l):p(d.component)&&(d.component.then(f,l),o(d.error)&&(e.errorComp=it(d.error,t)),o(d.loading)&&(e.loadingComp=it(d.loading,t),0===d.delay?e.loading=!0:setTimeout(function(){r(e.resolved)&&r(e.error)&&(e.loading=!0,u(!1))},d.delay||200)),o(d.timeout)&&setTimeout(function(){r(e.resolved)&&l(null)},d.timeout))),s=!1,e.loading?e.loadingComp:e.resolved}e.owners.push(n)}function ct(e){return e.isComment&&e.asyncFactory}function ut(e){if(Array.isArray(e))for(var t=0;t<e.length;t++){var n=e[t];if(o(n)&&(o(n.componentOptions)||ct(n)))return n}}function ft(e){e._events=Object.create(null),e._hasHookEvent=!1;var t=e.$options._parentListeners;t&&vt(e,t)}function lt(e,t){ja.$on(e,t)}function pt(e,t){ja.$off(e,t)}function dt(e,t){var n=ja;return function r(){null!==t.apply(null,arguments)&&n.$off(e,r)}}function vt(e,t,n){ja=e,ve(t,n||{},lt,pt,dt,e),ja=void 0}function ht(e){var t=Ra;return Ra=e,function(){Ra=t}}function mt(e){var t=e.$options,n=t.parent;if(n&&!t.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(e)}e.$parent=n,e.$root=n?n.$root:e,e.$children=[],e.$refs={},e._watcher=null,e._inactive=null,e._directInactive=!1,e._isMounted=!1,e._isDestroyed=!1,e._isBeingDestroyed=!1}function yt(e,t,n){e.$el=t,e.$options.render||(e.$options.render=da),xt(e,"beforeMount");var r;return r=function(){e._update(e._render(),n)},new Ja(e,r,A,{before:function(){e._isMounted&&!e._isDestroyed&&xt(e,"beforeUpdate")}},!0),n=!1,null==e.$vnode&&(e._isMounted=!0,xt(e,"mounted")),e}function gt(e,t,n,r,o){var i=r.data.scopedSlots,a=e.$scopedSlots,s=!!(i&&!i.$stable||a!==Ai&&!a.$stable||i&&e.$scopedSlots.$key!==i.$key),c=!!(o||e.$options._renderChildren||s);if(e.$options._parentVnode=r,e.$vnode=r,e._vnode&&(e._vnode.parent=r),e.$options._renderChildren=o,e.$attrs=r.data.attrs||Ai,e.$listeners=n||Ai,t&&e.$options.props){P(!1);for(var u=e._props,f=e.$options._propKeys||[],l=0;l<f.length;l++){var p=f[l],d=e.$options.props;u[p]=ee(p,d,t,e)}P(!0),e.$options.propsData=t}n=n||Ai;var v=e.$options._parentListeners;e.$options._parentListeners=n,vt(e,n,v),c&&(e.$slots=Ce(o,r.context),e.$forceUpdate())}function bt(e){for(;e&&(e=e.$parent);)if(e._inactive)return!0;return!1}function _t(e,t){if(t){if(e._directInactive=!1,bt(e))return}else if(e._directInactive)return;if(e._inactive||null===e._inactive){e._inactive=!1;for(var n=0;n<e.$children.length;n++)_t(e.$children[n]);xt(e,"activated")}}function wt(e,t){if(!(t&&(e._directInactive=!0,bt(e))||e._inactive)){e._inactive=!0;for(var n=0;n<e.$children.length;n++)wt(e.$children[n]);xt(e,"deactivated")}}function xt(e,t){I();var n=e.$options[t],r=t+" hook";if(n)for(var o=0,i=n.length;o<i;o++)ae(n[o],e,null,e,r);e._hasHookEvent&&e.$emit("hook:"+t),L()}function $t(){qa=Ma.length=Ba.length=0,Fa={},Ua=Ha=!1}function At(){za=Va(),Ha=!0;var e,t;for(Ma.sort(function(e,t){return e.id-t.id}),qa=0;qa<Ma.length;qa++)e=Ma[qa],e.before&&e.before(),t=e.id,Fa[t]=null,e.run();var n=Ba.slice(),r=Ma.slice();$t(),Tt(n),Ct(r),ia&&Fi.devtools&&ia.emit("flush")}function Ct(e){for(var t=e.length;t--;){var n=e[t],r=n.vm;r._watcher===n&&r._isMounted&&!r._isDestroyed&&xt(r,"updated")}}function kt(e){e._inactive=!1,Ba.push(e)}function Tt(e){for(var t=0;t<e.length;t++)e[t]._inactive=!0,_t(e[t],!0)}function St(e){var t=e.id;if(null==Fa[t]){if(Fa[t]=!0,Ha){for(var n=Ma.length-1;n>qa&&Ma[n].id>e.id;)n--;Ma.splice(n+1,0,e)}else Ma.push(e);Ua||(Ua=!0,fe(At))}}function Ot(e,t,n){Xa.get=function(){return this[t][n]},Xa.set=function(e){this[t][n]=e},Object.defineProperty(e,n,Xa)}function Et(e){e._watchers=[];var t=e.$options;t.props&&jt(e,t.props),t.methods&&Mt(e,t.methods),t.data?It(e):B(e._data={},!0),t.computed&&Nt(e,t.computed),t.watch&&t.watch!==Qi&&Bt(e,t.watch)}function jt(e,t){var n=e.$options.propsData||{},r=e._props={},o=e.$options._propKeys=[];!e.$parent||P(!1);for(var i in t)!function(i){o.push(i);var a=ee(i,t,n,e);F(r,i,a),i in e||Ot(e,"_props",i)}(i);P(!0)}function It(e){var t=e.$options.data;t=e._data="function"==typeof t?Lt(t,e):t||{},u(t)||(t={});for(var n=Object.keys(t),r=e.$options.props,o=(e.$options.methods,n.length);o--;){var i=n[o];r&&y(r,i)||S(i)||Ot(e,"_data",i)}B(t,!0)}function Lt(e,t){I();try{return e.call(t,t)}catch(e){return ie(e,t,"data()"),{}}finally{L()}}function Nt(e,t){var n=e._computedWatchers=Object.create(null),r=oa();for(var o in t){var i=t[o],a="function"==typeof i?i:i.get;r||(n[o]=new Ja(e,a||A,A,Wa)),o in e||Dt(e,o,i)}}function Dt(e,t,n){var r=!oa();"function"==typeof n?(Xa.get=r?Pt(t):Rt(n),Xa.set=A):(Xa.get=n.get?r&&!1!==n.cache?Pt(t):Rt(n.get):A,Xa.set=n.set||A),Object.defineProperty(e,t,Xa)}function Pt(e){return function(){var t=this._computedWatchers&&this._computedWatchers[e];if(t)return t.dirty&&t.evaluate(),ua.target&&t.depend(),t.value}}function Rt(e){return function(){return e.call(this,this)}}function Mt(e,t){e.$options.props;for(var n in t)e[n]="function"!=typeof t[n]?A:Ni(t[n],e)}function Bt(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var o=0;o<r.length;o++)Ft(e,n,r[o]);else Ft(e,n,r)}}function Ft(e,t,n,r){return u(n)&&(r=n,n=n.handler),"string"==typeof n&&(n=e[n]),e.$watch(t,n,r)}function Ut(e,t){var n=e.$options=Object.create(e.constructor.options),r=t._parentVnode;n.parent=t.parent,n._parentVnode=r;var o=r.componentOptions;n.propsData=o.propsData,n._parentListeners=o.listeners,n._renderChildren=o.children,n._componentTag=o.tag,t.render&&(n.render=t.render,n.staticRenderFns=t.staticRenderFns)}function Ht(e){var t=e.options;if(e.super){var n=Ht(e.super);if(n!==e.superOptions){e.superOptions=n;var r=qt(e);r&&x(e.extendOptions,r),t=e.options=Y(n,e.extendOptions),t.name&&(t.components[t.name]=e)}}return t}function qt(e){var t,n=e.options,r=e.sealedOptions;for(var o in n)n[o]!==r[o]&&(t||(t={}),t[o]=n[o]);return t}function zt(e){this._init(e)}function Vt(e){e.use=function(e){var t=this._installedPlugins||(this._installedPlugins=[]);if(t.indexOf(e)>-1)return this;var n=w(arguments,1);return n.unshift(this),"function"==typeof e.install?e.install.apply(e,n):"function"==typeof e&&e.apply(null,n),t.push(e),this}}function Kt(e){e.mixin=function(e){return this.options=Y(this.options,e),this}}function Jt(e){e.cid=0;var t=1;e.extend=function(e){e=e||{};var n=this,r=n.cid,o=e._Ctor||(e._Ctor={});if(o[r])return o[r];var i=e.name||n.options.name,a=function(e){this._init(e)};return a.prototype=Object.create(n.prototype),a.prototype.constructor=a,a.cid=t++,a.options=Y(n.options,e),a.super=n,a.options.props&&Xt(a),a.options.computed&&Wt(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,Mi.forEach(function(e){a[e]=n[e]}),i&&(a.options.components[i]=a),a.superOptions=n.options,a.extendOptions=e,a.sealedOptions=x({},a.options),o[r]=a,a}}function Xt(e){var t=e.options.props;for(var n in t)Ot(e.prototype,"_props",n)}function Wt(e){var t=e.options.computed;for(var n in t)Dt(e.prototype,n,t[n])}function Gt(e){Mi.forEach(function(t){e[t]=function(e,n){return n?("component"===t&&u(n)&&(n.name=n.name||e,n=this.options._base.extend(n)),"directive"===t&&"function"==typeof n&&(n={bind:n,update:n}),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}})}function Zt(e){return e&&(e.Ctor.options.name||e.tag)}function Yt(e,t){return Array.isArray(e)?e.indexOf(t)>-1:"string"==typeof e?e.split(",").indexOf(t)>-1:!!f(e)&&e.test(t)}function Qt(e,t){var n=e.cache,r=e.keys,o=e._vnode;for(var i in n){var a=n[i];if(a){var s=Zt(a.componentOptions);s&&!t(s)&&en(n,i,r,o)}}}function en(e,t,n,r){var o=e[t];!o||r&&o.tag===r.tag||o.componentInstance.$destroy(),e[t]=null,m(n,t)}function tn(e){for(var t=e.data,n=e,r=e;o(r.componentInstance);)(r=r.componentInstance._vnode)&&r.data&&(t=nn(r.data,t));for(;o(n=n.parent);)n&&n.data&&(t=nn(t,n.data));return rn(t.staticClass,t.class)}function nn(e,t){return{staticClass:on(e.staticClass,t.staticClass),class:o(e.class)?[e.class,t.class]:t.class}}function rn(e,t){return o(e)||o(t)?on(e,an(t)):""}function on(e,t){return e?t?e+" "+t:e:t||""}function an(e){return Array.isArray(e)?sn(e):c(e)?cn(e):"string"==typeof e?e:""}function sn(e){for(var t,n="",r=0,i=e.length;r<i;r++)o(t=an(e[r]))&&""!==t&&(n&&(n+=" "),n+=t);return n}function cn(e){var t="";for(var n in e)e[n]&&(t&&(t+=" "),t+=n);return t}function un(e){return $s(e)?"svg":"math"===e?"math":void 0}function fn(e){if(!zi)return!0;if(Cs(e))return!1;if(e=e.toLowerCase(),null!=ks[e])return ks[e];var t=document.createElement(e);return e.indexOf("-")>-1?ks[e]=t.constructor===window.HTMLUnknownElement||t.constructor===window.HTMLElement:ks[e]=/HTMLUnknownElement/.test(t.toString())}function ln(e){if("string"==typeof e){return document.querySelector(e)||document.createElement("div")}return e}function pn(e,t){var n=document.createElement(e);return"select"!==e?n:(t.data&&t.data.attrs&&void 0!==t.data.attrs.multiple&&n.setAttribute("multiple","multiple"),n)}function dn(e,t){return document.createElementNS(ws[e],t)}function vn(e){return document.createTextNode(e)}function hn(e){return document.createComment(e)}function mn(e,t,n){e.insertBefore(t,n)}function yn(e,t){e.removeChild(t)}function gn(e,t){e.appendChild(t)}function bn(e){return e.parentNode}function _n(e){return e.nextSibling}function wn(e){return e.tagName}function xn(e,t){e.textContent=t}function $n(e,t){e.setAttribute(t,"")}function An(e,t){var n=e.data.ref;if(o(n)){var r=e.context,i=e.componentInstance||e.elm,a=r.$refs;t?Array.isArray(a[n])?m(a[n],i):a[n]===i&&(a[n]=void 0):e.data.refInFor?Array.isArray(a[n])?a[n].indexOf(i)<0&&a[n].push(i):a[n]=[i]:a[n]=i}}function Cn(e,t){return e.key===t.key&&(e.tag===t.tag&&e.isComment===t.isComment&&o(e.data)===o(t.data)&&kn(e,t)||i(e.isAsyncPlaceholder)&&e.asyncFactory===t.asyncFactory&&r(t.asyncFactory.error))}function kn(e,t){if("input"!==e.tag)return!0;var n,r=o(n=e.data)&&o(n=n.attrs)&&n.type,i=o(n=t.data)&&o(n=n.attrs)&&n.type;return r===i||Ts(r)&&Ts(i)}function Tn(e,t,n){var r,i,a={};for(r=t;r<=n;++r)i=e[r].key,o(i)&&(a[i]=r);return a}function Sn(e,t){(e.data.directives||t.data.directives)&&On(e,t)}function On(e,t){var n,r,o,i=e===Es,a=t===Es,s=En(e.data.directives,e.context),c=En(t.data.directives,t.context),u=[],f=[];for(n in c)r=s[n],o=c[n],r?(o.oldValue=r.value,o.oldArg=r.arg,In(o,"update",t,e),o.def&&o.def.componentUpdated&&f.push(o)):(In(o,"bind",t,e),o.def&&o.def.inserted&&u.push(o));if(u.length){var l=function(){for(var n=0;n<u.length;n++)In(u[n],"inserted",t,e)};i?he(t,"insert",l):l()}if(f.length&&he(t,"postpatch",function(){for(var n=0;n<f.length;n++)In(f[n],"componentUpdated",t,e)}),!i)for(n in s)c[n]||In(s[n],"unbind",e,e,a)}function En(e,t){var n=Object.create(null);if(!e)return n;var r,o;for(r=0;r<e.length;r++)o=e[r],o.modifiers||(o.modifiers=Ls),n[jn(o)]=o,o.def=Q(t.$options,"directives",o.name,!0);return n}function jn(e){return e.rawName||e.name+"."+Object.keys(e.modifiers||{}).join(".")}function In(e,t,n,r,o){var i=e.def&&e.def[t];if(i)try{i(n.elm,e,n,r,o)}catch(r){ie(r,n.context,"directive "+e.name+" "+t+" hook")}}function Ln(e,t){var n=t.componentOptions;if(!(o(n)&&!1===n.Ctor.options.inheritAttrs||r(e.data.attrs)&&r(t.data.attrs))){var i,a,s=t.elm,c=e.data.attrs||{},u=t.data.attrs||{};o(u.__ob__)&&(u=t.data.attrs=x({},u));for(i in u)a=u[i],c[i]!==a&&Nn(s,i,a);(Xi||Gi)&&u.value!==c.value&&Nn(s,"value",u.value);for(i in c)r(u[i])&&(gs(i)?s.removeAttributeNS(ys,bs(i)):ds(i)||s.removeAttribute(i))}}function Nn(e,t,n){e.tagName.indexOf("-")>-1?Dn(e,t,n):ms(t)?_s(n)?e.removeAttribute(t):(n="allowfullscreen"===t&&"EMBED"===e.tagName?"true":t,e.setAttribute(t,n)):ds(t)?e.setAttribute(t,hs(t,n)):gs(t)?_s(n)?e.removeAttributeNS(ys,bs(t)):e.setAttributeNS(ys,t,n):Dn(e,t,n)}function Dn(e,t,n){if(_s(n))e.removeAttribute(t);else{if(Xi&&!Wi&&"TEXTAREA"===e.tagName&&"placeholder"===t&&""!==n&&!e.__ieph){var r=function(t){t.stopImmediatePropagation(),e.removeEventListener("input",r)};e.addEventListener("input",r),e.__ieph=!0}e.setAttribute(t,n)}}function Pn(e,t){var n=t.elm,i=t.data,a=e.data;if(!(r(i.staticClass)&&r(i.class)&&(r(a)||r(a.staticClass)&&r(a.class)))){var s=tn(t),c=n._transitionClasses;o(c)&&(s=on(s,an(c))),s!==n._prevClass&&(n.setAttribute("class",s),n._prevClass=s)}}function Rn(e){function t(){(a||(a=[])).push(e.slice(v,o).trim()),v=o+1}var n,r,o,i,a,s=!1,c=!1,u=!1,f=!1,l=0,p=0,d=0,v=0;for(o=0;o<e.length;o++)if(r=n,n=e.charCodeAt(o),s)39===n&&92!==r&&(s=!1);else if(c)34===n&&92!==r&&(c=!1);else if(u)96===n&&92!==r&&(u=!1);else if(f)47===n&&92!==r&&(f=!1);else if(124!==n||124===e.charCodeAt(o+1)||124===e.charCodeAt(o-1)||l||p||d){switch(n){case 34:c=!0;break;case 39:s=!0;break;case 96:u=!0;break;case 40:d++;break;case 41:d--;break;case 91:p++;break;case 93:p--;break;case 123:l++;break;case 125:l--}if(47===n){for(var h=o-1,m=void 0;h>=0&&" "===(m=e.charAt(h));h--);m&&Rs.test(m)||(f=!0)}}else void 0===i?(v=o+1,i=e.slice(0,o).trim()):t();if(void 0===i?i=e.slice(0,o).trim():0!==v&&t(),a)for(o=0;o<a.length;o++)i=Mn(i,a[o]);return i}function Mn(e,t){var n=t.indexOf("(");if(n<0)return'_f("'+t+'")('+e+")";var r=t.slice(0,n),o=t.slice(n+1);return'_f("'+r+'")('+e+(")"!==o?","+o:o)}function Bn(e,t){console.error("[Vue compiler]: "+e)}function Fn(e,t){return e?e.map(function(e){return e[t]}).filter(function(e){return e}):[]}function Un(e,t,n,r,o){(e.props||(e.props=[])).push(Zn({name:t,value:n,dynamic:o},r)),e.plain=!1}function Hn(e,t,n,r,o){(o?e.dynamicAttrs||(e.dynamicAttrs=[]):e.attrs||(e.attrs=[])).push(Zn({name:t,value:n,dynamic:o},r)),e.plain=!1}function qn(e,t,n,r){e.attrsMap[t]=n,e.attrsList.push(Zn({name:t,value:n},r))}function zn(e,t,n,r,o,i,a,s){(e.directives||(e.directives=[])).push(Zn({name:t,rawName:n,value:r,arg:o,isDynamicArg:i,modifiers:a},s)),e.plain=!1}function Vn(e,t,n){return n?"_p("+t+',"'+e+'")':e+t}function Kn(e,t,n,r,o,i,a,s){r=r||Ai,r.right?s?t="("+t+")==='click'?'contextmenu':("+t+")":"click"===t&&(t="contextmenu",delete r.right):r.middle&&(s?t="("+t+")==='click'?'mouseup':("+t+")":"click"===t&&(t="mouseup")),r.capture&&(delete r.capture,t=Vn("!",t,s)),r.once&&(delete r.once,t=Vn("~",t,s)),r.passive&&(delete r.passive,t=Vn("&",t,s));var c;r.native?(delete r.native,c=e.nativeEvents||(e.nativeEvents={})):c=e.events||(e.events={});var u=Zn({value:n.trim(),dynamic:s},a);r!==Ai&&(u.modifiers=r);var f=c[t];Array.isArray(f)?o?f.unshift(u):f.push(u):c[t]=f?o?[u,f]:[f,u]:u,e.plain=!1}function Jn(e,t){return e.rawAttrsMap[":"+t]||e.rawAttrsMap["v-bind:"+t]||e.rawAttrsMap[t]}function Xn(e,t,n){var r=Wn(e,":"+t)||Wn(e,"v-bind:"+t);if(null!=r)return Rn(r);if(!1!==n){var o=Wn(e,t);if(null!=o)return JSON.stringify(o)}}function Wn(e,t,n){var r;if(null!=(r=e.attrsMap[t]))for(var o=e.attrsList,i=0,a=o.length;i<a;i++)if(o[i].name===t){o.splice(i,1);break}return n&&delete e.attrsMap[t],r}function Gn(e,t){for(var n=e.attrsList,r=0,o=n.length;r<o;r++){var i=n[r];if(t.test(i.name))return n.splice(r,1),i}}function Zn(e,t){return t&&(null!=t.start&&(e.start=t.start),null!=t.end&&(e.end=t.end)),e}function Yn(e,t,n){var r=n||{},o=r.number,i=r.trim,a="$$v";i&&(a="(typeof $$v === 'string'? $$v.trim(): $$v)"),o&&(a="_n("+a+")");var s=Qn(t,a);e.model={value:"("+t+")",expression:JSON.stringify(t),callback:"function ($$v) {"+s+"}"}}function Qn(e,t){var n=er(e);return null===n.key?e+"="+t:"$set("+n.exp+", "+n.key+", "+t+")"}function er(e){if(e=e.trim(),es=e.length,e.indexOf("[")<0||e.lastIndexOf("]")<es-1)return rs=e.lastIndexOf("."),rs>-1?{exp:e.slice(0,rs),key:'"'+e.slice(rs+1)+'"'}:{exp:e,key:null};for(ts=e,rs=os=is=0;!nr();)ns=tr(),rr(ns)?ir(ns):91===ns&&or(ns);return{exp:e.slice(0,os),key:e.slice(os+1,is)}}function tr(){return ts.charCodeAt(++rs)}function nr(){return rs>=es}function rr(e){return 34===e||39===e}function or(e){var t=1;for(os=rs;!nr();)if(e=tr(),rr(e))ir(e);else if(91===e&&t++,93===e&&t--,0===t){is=rs;break}}function ir(e){for(var t=e;!nr()&&(e=tr())!==t;);}function ar(e,t,n){as=n;var r=t.value,o=t.modifiers,i=e.tag,a=e.attrsMap.type;if(e.component)return Yn(e,r,o),!1;if("select"===i)ur(e,r,o);else if("input"===i&&"checkbox"===a)sr(e,r,o);else if("input"===i&&"radio"===a)cr(e,r,o);else if("input"===i||"textarea"===i)fr(e,r,o);else if(!Fi.isReservedTag(i))return Yn(e,r,o),!1;return!0}function sr(e,t,n){var r=n&&n.number,o=Xn(e,"value")||"null",i=Xn(e,"true-value")||"true",a=Xn(e,"false-value")||"false";Un(e,"checked","Array.isArray("+t+")?_i("+t+","+o+")>-1"+("true"===i?":("+t+")":":_q("+t+","+i+")")),Kn(e,"change","var $$a="+t+",$$el=$event.target,$$c=$$el.checked?("+i+"):("+a+");if(Array.isArray($$a)){var $$v="+(r?"_n("+o+")":o)+",$$i=_i($$a,$$v);if($$el.checked){$$i<0&&("+Qn(t,"$$a.concat([$$v])")+")}else{$$i>-1&&("+Qn(t,"$$a.slice(0,$$i).concat($$a.slice($$i+1))")+")}}else{"+Qn(t,"$$c")+"}",null,!0)}function cr(e,t,n){var r=n&&n.number,o=Xn(e,"value")||"null";o=r?"_n("+o+")":o,Un(e,"checked","_q("+t+","+o+")"),Kn(e,"change",Qn(t,o),null,!0)}function ur(e,t,n){var r=n&&n.number,o='Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = "_value" in o ? o._value : o.value;return '+(r?"_n(val)":"val")+"})",i="var $$selectedVal = "+o+";";i=i+" "+Qn(t,"$event.target.multiple ? $$selectedVal : $$selectedVal[0]"),Kn(e,"change",i,null,!0)}function fr(e,t,n){var r=e.attrsMap.type,o=n||{},i=o.lazy,a=o.number,s=o.trim,c=!i&&"range"!==r,u=i?"change":"range"===r?Ms:"input",f="$event.target.value";s&&(f="$event.target.value.trim()"),a&&(f="_n("+f+")");var l=Qn(t,f);c&&(l="if($event.target.composing)return;"+l),Un(e,"value","("+t+")"),Kn(e,u,l,null,!0),(s||a)&&Kn(e,"blur","$forceUpdate()")}function lr(e){if(o(e[Ms])){var t=Xi?"change":"input";e[t]=[].concat(e[Ms],e[t]||[]),delete e[Ms]}o(e[Bs])&&(e.change=[].concat(e[Bs],e.change||[]),delete e[Bs])}function pr(e,t,n){var r=ss;return function o(){null!==t.apply(null,arguments)&&vr(e,o,n,r)}}function dr(e,t,n,r){if(Fs){var o=za,i=t;t=i._wrapper=function(e){if(e.target===e.currentTarget||e.timeStamp>=o||0===e.timeStamp||e.target.ownerDocument!==document)return i.apply(this,arguments)}}ss.addEventListener(e,t,ea?{capture:n,passive:r}:n)}function vr(e,t,n,r){(r||ss).removeEventListener(e,t._wrapper||t,n)}function hr(e,t){if(!r(e.data.on)||!r(t.data.on)){var n=t.data.on||{},o=e.data.on||{};ss=t.elm,lr(n),ve(n,o,dr,vr,pr,t.context),ss=void 0}}function mr(e,t){if(!r(e.data.domProps)||!r(t.data.domProps)){var n,i,a=t.elm,s=e.data.domProps||{},c=t.data.domProps||{};o(c.__ob__)&&(c=t.data.domProps=x({},c));for(n in s)r(c[n])&&(a[n]="");for(n in c){if(i=c[n],"textContent"===n||"innerHTML"===n){if(t.children&&(t.children.length=0),i===s[n])continue;1===a.childNodes.length&&a.removeChild(a.childNodes[0])}if("value"===n&&"PROGRESS"!==a.tagName){a._value=i;var u=r(i)?"":String(i);yr(a,u)&&(a.value=u)}else if("innerHTML"===n&&$s(a.tagName)&&r(a.innerHTML)){cs=cs||document.createElement("div"),cs.innerHTML="<svg>"+i+"</svg>";for(var f=cs.firstChild;a.firstChild;)a.removeChild(a.firstChild);for(;f.firstChild;)a.appendChild(f.firstChild)}else if(i!==s[n])try{a[n]=i}catch(e){}}}}function yr(e,t){return!e.composing&&("OPTION"===e.tagName||gr(e,t)||br(e,t))}function gr(e,t){var n=!0;try{n=document.activeElement!==e}catch(e){}return n&&e.value!==t}function br(e,t){var n=e.value,r=e._vModifiers;if(o(r)){if(r.number)return v(n)!==v(t);if(r.trim)return n.trim()!==t.trim()}return n!==t}function _r(e){var t=wr(e.style);return e.staticStyle?x(e.staticStyle,t):t}function wr(e){return Array.isArray(e)?$(e):"string"==typeof e?qs(e):e}function xr(e,t){var n,r={};if(t)for(var o=e;o.componentInstance;)(o=o.componentInstance._vnode)&&o.data&&(n=_r(o.data))&&x(r,n);(n=_r(e.data))&&x(r,n);for(var i=e;i=i.parent;)i.data&&(n=_r(i.data))&&x(r,n);return r}function $r(e,t){var n=t.data,i=e.data;if(!(r(n.staticStyle)&&r(n.style)&&r(i.staticStyle)&&r(i.style))){var a,s,c=t.elm,u=i.staticStyle,f=i.normalizedStyle||i.style||{},l=u||f,p=wr(t.data.style)||{};t.data.normalizedStyle=o(p.__ob__)?x({},p):p;var d=xr(t,!0);for(s in l)r(d[s])&&Ks(c,s,"");for(s in d)(a=d[s])!==l[s]&&Ks(c,s,null==a?"":a)}}function Ar(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(Gs).forEach(function(t){return e.classList.add(t)}):e.classList.add(t);else{var n=" "+(e.getAttribute("class")||"")+" ";n.indexOf(" "+t+" ")<0&&e.setAttribute("class",(n+t).trim())}}function Cr(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(Gs).forEach(function(t){return e.classList.remove(t)}):e.classList.remove(t),e.classList.length||e.removeAttribute("class");else{for(var n=" "+(e.getAttribute("class")||"")+" ",r=" "+t+" ";n.indexOf(r)>=0;)n=n.replace(r," ");n=n.trim(),n?e.setAttribute("class",n):e.removeAttribute("class")}}function kr(e){if(e){if("object"==typeof e){var t={};return!1!==e.css&&x(t,Zs(e.name||"v")),x(t,e),t}return"string"==typeof e?Zs(e):void 0}}function Tr(e){ic(function(){ic(e)})}function Sr(e,t){var n=e._transitionClasses||(e._transitionClasses=[]);n.indexOf(t)<0&&(n.push(t),Ar(e,t))}function Or(e,t){e._transitionClasses&&m(e._transitionClasses,t),Cr(e,t)}function Er(e,t,n){var r=jr(e,t),o=r.type,i=r.timeout,a=r.propCount;if(!o)return n();var s=o===Qs?nc:oc,c=0,u=function(){e.removeEventListener(s,f),n()},f=function(t){t.target===e&&++c>=a&&u()};setTimeout(function(){c<a&&u()},i+1),e.addEventListener(s,f)}function jr(e,t){var n,r=window.getComputedStyle(e),o=(r[tc+"Delay"]||"").split(", "),i=(r[tc+"Duration"]||"").split(", "),a=Ir(o,i),s=(r[rc+"Delay"]||"").split(", "),c=(r[rc+"Duration"]||"").split(", "),u=Ir(s,c),f=0,l=0;return t===Qs?a>0&&(n=Qs,f=a,l=i.length):t===ec?u>0&&(n=ec,f=u,l=c.length):(f=Math.max(a,u),n=f>0?a>u?Qs:ec:null,l=n?n===Qs?i.length:c.length:0),{type:n,timeout:f,propCount:l,hasTransform:n===Qs&&ac.test(r[tc+"Property"])}}function Ir(e,t){for(;e.length<t.length;)e=e.concat(e);return Math.max.apply(null,t.map(function(t,n){return Lr(t)+Lr(e[n])}))}function Lr(e){return 1e3*Number(e.slice(0,-1).replace(",","."))}function Nr(e,t){var n=e.elm;o(n._leaveCb)&&(n._leaveCb.cancelled=!0,n._leaveCb());var i=kr(e.data.transition);if(!r(i)&&!o(n._enterCb)&&1===n.nodeType){for(var a=i.css,s=i.type,u=i.enterClass,f=i.enterToClass,l=i.enterActiveClass,p=i.appearClass,d=i.appearToClass,h=i.appearActiveClass,m=i.beforeEnter,y=i.enter,g=i.afterEnter,b=i.enterCancelled,_=i.beforeAppear,w=i.appear,x=i.afterAppear,$=i.appearCancelled,A=i.duration,C=Ra,k=Ra.$vnode;k&&k.parent;)k=k.parent,C=k.context;var S=!C._isMounted||!e.isRootInsert;if(!S||w||""===w){var O=S&&p?p:u,E=S&&h?h:l,j=S&&d?d:f,I=S?_||m:m,L=S&&"function"==typeof w?w:y,N=S?x||g:g,D=S?$||b:b,P=v(c(A)?A.enter:A),R=!1!==a&&!Wi,M=Rr(L),B=n._enterCb=T(function(){R&&(Or(n,j),Or(n,E)),B.cancelled?(R&&Or(n,O),D&&D(n)):N&&N(n),n._enterCb=null});e.data.show||he(e,"insert",function(){var t=n.parentNode,r=t&&t._pending&&t._pending[e.key];r&&r.tag===e.tag&&r.elm._leaveCb&&r.elm._leaveCb(),L&&L(n,B)}),I&&I(n),R&&(Sr(n,O),Sr(n,E),Tr(function(){Or(n,O),B.cancelled||(Sr(n,j),M||(Pr(P)?setTimeout(B,P):Er(n,s,B)))})),e.data.show&&(t&&t(),L&&L(n,B)),R||M||B()}}}function Dr(e,t){function n(){$.cancelled||(!e.data.show&&i.parentNode&&((i.parentNode._pending||(i.parentNode._pending={}))[e.key]=e),d&&d(i),_&&(Sr(i,f),Sr(i,p),Tr(function(){Or(i,f),$.cancelled||(Sr(i,l),w||(Pr(x)?setTimeout($,x):Er(i,u,$)))})),h&&h(i,$),_||w||$())}var i=e.elm;o(i._enterCb)&&(i._enterCb.cancelled=!0,i._enterCb());var a=kr(e.data.transition);if(r(a)||1!==i.nodeType)return t();if(!o(i._leaveCb)){var s=a.css,u=a.type,f=a.leaveClass,l=a.leaveToClass,p=a.leaveActiveClass,d=a.beforeLeave,h=a.leave,m=a.afterLeave,y=a.leaveCancelled,g=a.delayLeave,b=a.duration,_=!1!==s&&!Wi,w=Rr(h),x=v(c(b)?b.leave:b),$=i._leaveCb=T(function(){i.parentNode&&i.parentNode._pending&&(i.parentNode._pending[e.key]=null),_&&(Or(i,l),Or(i,p)),$.cancelled?(_&&Or(i,f),y&&y(i)):(t(),m&&m(i)),i._leaveCb=null});g?g(n):n()}}function Pr(e){return"number"==typeof e&&!isNaN(e)}function Rr(e){if(r(e))return!1;var t=e.fns;return o(t)?Rr(Array.isArray(t)?t[0]:t):(e._length||e.length)>1}function Mr(e,t){!0!==t.data.show&&Nr(t)}function Br(e,t,n){Fr(e,t,n),(Xi||Gi)&&setTimeout(function(){Fr(e,t,n)},0)}function Fr(e,t,n){var r=t.value,o=e.multiple;if(!o||Array.isArray(r)){for(var i,a,s=0,c=e.options.length;s<c;s++)if(a=e.options[s],o)i=k(r,Hr(a))>-1,a.selected!==i&&(a.selected=i);else if(C(Hr(a),r))return void(e.selectedIndex!==s&&(e.selectedIndex=s));o||(e.selectedIndex=-1)}}function Ur(e,t){return t.every(function(t){return!C(t,e)})}function Hr(e){return"_value"in e?e._value:e.value}function qr(e){e.target.composing=!0}function zr(e){e.target.composing&&(e.target.composing=!1,Vr(e.target,"input"))}function Vr(e,t){var n=document.createEvent("HTMLEvents");n.initEvent(t,!0,!0),e.dispatchEvent(n)}function Kr(e){return!e.componentInstance||e.data&&e.data.transition?e:Kr(e.componentInstance._vnode)}function Jr(e){var t=e&&e.componentOptions;return t&&t.Ctor.options.abstract?Jr(ut(t.children)):e}function Xr(e){var t={},n=e.$options;for(var r in n.propsData)t[r]=e[r];var o=n._parentListeners;for(var i in o)t[Ei(i)]=o[i];return t}function Wr(e,t){if(/\d-keep-alive$/.test(t.tag))return e("keep-alive",{props:t.componentOptions.propsData})}function Gr(e){for(;e=e.parent;)if(e.data.transition)return!0}function Zr(e,t){return t.key===e.key&&t.tag===e.tag}function Yr(e){e.elm._moveCb&&e.elm._moveCb(),e.elm._enterCb&&e.elm._enterCb()}function Qr(e){e.data.newPos=e.elm.getBoundingClientRect()}function eo(e){var t=e.data.pos,n=e.data.newPos,r=t.left-n.left,o=t.top-n.top;if(r||o){e.data.moved=!0;var i=e.elm.style;i.transform=i.WebkitTransform="translate("+r+"px,"+o+"px)",i.transitionDuration="0s"}}function to(e,t){var n=t?Pc(t):Nc;if(n.test(e)){for(var r,o,i,a=[],s=[],c=n.lastIndex=0;r=n.exec(e);){(o=r.index)>c&&(s.push(i=e.slice(c,o)),a.push(JSON.stringify(i)));var u=Rn(r[1].trim());a.push("_s("+u+")"),s.push({"@binding":u}),c=o+r[0].length}return c<e.length&&(s.push(i=e.slice(c)),a.push(JSON.stringify(i))),{expression:a.join("+"),tokens:s}}}function no(e,t){var n=(t.warn,Wn(e,"class"));n&&(e.staticClass=JSON.stringify(n));var r=Xn(e,"class",!1);r&&(e.classBinding=r)}function ro(e){var t="";return e.staticClass&&(t+="staticClass:"+e.staticClass+","),e.classBinding&&(t+="class:"+e.classBinding+","),t}function oo(e,t){var n=(t.warn,Wn(e,"style"));n&&(e.staticStyle=JSON.stringify(qs(n)));var r=Xn(e,"style",!1);r&&(e.styleBinding=r)}function io(e){var t="";return e.staticStyle&&(t+="staticStyle:"+e.staticStyle+","),e.styleBinding&&(t+="style:("+e.styleBinding+"),"),t}function ao(e,t){var n=t?ru:nu;return e.replace(n,function(e){return tu[e]})}function so(e,t){function n(t){f+=t,e=e.substring(t)}function r(e,n,r){var o,s;if(null==n&&(n=f),null==r&&(r=f),e)for(s=e.toLowerCase(),o=a.length-1;o>=0&&a[o].lowerCasedTag!==s;o--);else o=0;if(o>=0){for(var c=a.length-1;c>=o;c--)t.end&&t.end(a[c].tag,n,r);a.length=o,i=o&&a[o-1].tag}else"br"===s?t.start&&t.start(e,[],!0,n,r):"p"===s&&(t.start&&t.start(e,[],!1,n,r),t.end&&t.end(e,n,r))}for(var o,i,a=[],s=t.expectHTML,c=t.isUnaryTag||Di,u=t.canBeLeftOpenTag||Di,f=0;e;){if(o=e,i&&Qc(i)){var l=0,p=i.toLowerCase(),d=eu[p]||(eu[p]=new RegExp("([\\s\\S]*?)(</"+p+"[^>]*>)","i")),v=e.replace(d,function(e,n,r){return l=r.length,Qc(p)||"noscript"===p||(n=n.replace(/<!\--([\s\S]*?)-->/g,"$1").replace(/<!\[CDATA\[([\s\S]*?)]]>/g,"$1")),iu(p,n)&&(n=n.slice(1)),t.chars&&t.chars(n),""});f+=e.length-v.length,e=v,r(p,f-l,f)}else{var h=e.indexOf("<");if(0===h){if(Zc.test(e)){var m=e.indexOf("--\x3e");if(m>=0){t.shouldKeepComment&&t.comment(e.substring(4,m),f,f+m+3),n(m+3);continue}}if(Yc.test(e)){var y=e.indexOf("]>");if(y>=0){n(y+2);continue}}var g=e.match(Gc);if(g){n(g[0].length);continue}var b=e.match(Wc);if(b){var _=f;n(b[0].length),r(b[1],_,f);continue}var w=function(){var t=e.match(Jc);if(t){var r={tagName:t[1],attrs:[],start:f};n(t[0].length);for(var o,i;!(o=e.match(Xc))&&(i=e.match(zc)||e.match(qc));)i.start=f,n(i[0].length),i.end=f,r.attrs.push(i);if(o)return r.unarySlash=o[1],n(o[0].length),r.end=f,r}}();if(w){!function(e){var n=e.tagName,o=e.unarySlash;s&&("p"===i&&Hc(n)&&r(i),u(n)&&i===n&&r(n));for(var f=c(n)||!!o,l=e.attrs.length,p=new Array(l),d=0;d<l;d++){var v=e.attrs[d],h=v[3]||v[4]||v[5]||"",m="a"===n&&"href"===v[1]?t.shouldDecodeNewlinesForHref:t.shouldDecodeNewlines;p[d]={name:v[1],value:ao(h,m)}}f||(a.push({tag:n,lowerCasedTag:n.toLowerCase(),attrs:p,start:e.start,end:e.end}),i=n),t.start&&t.start(n,p,f,e.start,e.end)}(w),iu(w.tagName,e)&&n(1);continue}}var x=void 0,$=void 0,A=void 0;if(h>=0){for($=e.slice(h);!(Wc.test($)||Jc.test($)||Zc.test($)||Yc.test($)||(A=$.indexOf("<",1))<0);)h+=A,$=e.slice(h);x=e.substring(0,h)}h<0&&(x=e),x&&n(x.length),t.chars&&x&&t.chars(x,f-x.length,f)}if(e===o){t.chars&&t.chars(e);break}}r()}function co(e,t,n){return{type:1,tag:e,attrsList:t,attrsMap:Eo(t),rawAttrsMap:{},parent:n,children:[]}}function uo(e,t){function n(e){if(r(e),f||e.processed||(e=po(e,t)),s.length||e===i||i.if&&(e.elseif||e.else)&&wo(i,{exp:e.elseif,block:e}),a&&!e.forbidden)if(e.elseif||e.else)bo(e,a);else{if(e.slotScope){var n=e.slotTarget||'"default"';(a.scopedSlots||(a.scopedSlots={}))[n]=e}a.children.push(e),e.parent=a}e.children=e.children.filter(function(e){return!e.slotScope}),r(e),e.pre&&(f=!1),Tc(e.tag)&&(l=!1);for(var o=0;o<kc.length;o++)kc[o](e,t)}function r(e){if(!l)for(var t;(t=e.children[e.children.length-1])&&3===t.type&&" "===t.text;)e.children.pop()}xc=t.warn||Bn,Tc=t.isPreTag||Di,Sc=t.mustUseProp||Di,Oc=t.getTagNamespace||Di;var o=t.isReservedTag||Di;Ec=function(e){return!!e.component||!o(e.tag)},Ac=Fn(t.modules,"transformNode"),Cc=Fn(t.modules,"preTransformNode"),kc=Fn(t.modules,"postTransformNode"),$c=t.delimiters;var i,a,s=[],c=!1!==t.preserveWhitespace,u=t.whitespace,f=!1,l=!1;return so(e,{warn:xc,expectHTML:t.expectHTML,isUnaryTag:t.isUnaryTag,canBeLeftOpenTag:t.canBeLeftOpenTag,shouldDecodeNewlines:t.shouldDecodeNewlines,shouldDecodeNewlinesForHref:t.shouldDecodeNewlinesForHref,shouldKeepComment:t.comments,outputSourceRange:t.outputSourceRange,start:function(e,r,o,c){var u=a&&a.ns||Oc(e);Xi&&"svg"===u&&(r=Lo(r));var p=co(e,r,a);u&&(p.ns=u),Io(p)&&!oa()&&(p.forbidden=!0);for(var d=0;d<Cc.length;d++)p=Cc[d](p,t)||p;f||(fo(p),p.pre&&(f=!0)),Tc(p.tag)&&(l=!0),f?lo(p):p.processed||(mo(p),go(p),xo(p)),i||(i=p),o?n(p):(a=p,s.push(p))},end:function(e,t,r){var o=s[s.length-1];s.length-=1,a=s[s.length-1],n(o)},chars:function(e,t,n){if(a&&(!Xi||"textarea"!==a.tag||a.attrsMap.placeholder!==e)){var r=a.children;if(e=l||e.trim()?jo(a)?e:gu(e):r.length?u?"condense"===u&&mu.test(e)?"":" ":c?" ":"":""){"condense"===u&&(e=e.replace(yu," "));var o,i;!f&&" "!==e&&(o=to(e,$c))?i={type:2,expression:o.expression,tokens:o.tokens,text:e}:" "===e&&r.length&&" "===r[r.length-1].text||(i={type:3,text:e}),i&&r.push(i)}}},comment:function(e,t,n){if(a){var r={type:3,text:e,isComment:!0};a.children.push(r)}}}),i}function fo(e){null!=Wn(e,"v-pre")&&(e.pre=!0)}function lo(e){var t=e.attrsList,n=t.length;if(n)for(var r=e.attrs=new Array(n),o=0;o<n;o++)r[o]={name:t[o].name,value:JSON.stringify(t[o].value)},null!=t[o].start&&(r[o].start=t[o].start,r[o].end=t[o].end);else e.pre||(e.plain=!0)}function po(e,t){vo(e),e.plain=!e.key&&!e.scopedSlots&&!e.attrsList.length,ho(e),$o(e),Co(e),ko(e);for(var n=0;n<Ac.length;n++)e=Ac[n](e,t)||e;return To(e),e}function vo(e){var t=Xn(e,"key");t&&(e.key=t)}function ho(e){var t=Xn(e,"ref");t&&(e.ref=t,e.refInFor=So(e))}function mo(e){var t;if(t=Wn(e,"v-for")){var n=yo(t);n&&x(e,n)}}function yo(e){var t=e.match(cu);if(t){var n={};n.for=t[2].trim();var r=t[1].trim().replace(fu,""),o=r.match(uu);return o?(n.alias=r.replace(uu,"").trim(),n.iterator1=o[1].trim(),o[2]&&(n.iterator2=o[2].trim())):n.alias=r,n}}function go(e){var t=Wn(e,"v-if");if(t)e.if=t,wo(e,{exp:t,block:e});else{null!=Wn(e,"v-else")&&(e.else=!0);var n=Wn(e,"v-else-if");n&&(e.elseif=n)}}function bo(e,t){var n=_o(t.children);n&&n.if&&wo(n,{exp:e.elseif,block:e})}function _o(e){for(var t=e.length;t--;){if(1===e[t].type)return e[t];e.pop()}}function wo(e,t){e.ifConditions||(e.ifConditions=[]),e.ifConditions.push(t)}function xo(e){null!=Wn(e,"v-once")&&(e.once=!0)}function $o(e){var t;"template"===e.tag?(t=Wn(e,"scope"),e.slotScope=t||Wn(e,"slot-scope")):(t=Wn(e,"slot-scope"))&&(e.slotScope=t);var n=Xn(e,"slot");if(n&&(e.slotTarget='""'===n?'"default"':n,e.slotTargetDynamic=!(!e.attrsMap[":slot"]&&!e.attrsMap["v-bind:slot"]),"template"===e.tag||e.slotScope||Hn(e,"slot",n,Jn(e,"slot"))),"template"===e.tag){var r=Gn(e,hu);if(r){var o=Ao(r),i=o.name,a=o.dynamic;e.slotTarget=i,e.slotTargetDynamic=a,e.slotScope=r.value||bu}}else{var s=Gn(e,hu);if(s){var c=e.scopedSlots||(e.scopedSlots={}),u=Ao(s),f=u.name,l=u.dynamic,p=c[f]=co("template",[],e);p.slotTarget=f,p.slotTargetDynamic=l,p.children=e.children.filter(function(e){if(!e.slotScope)return e.parent=p,!0}),p.slotScope=s.value||bu,e.children=[],e.plain=!1}}}function Ao(e){var t=e.name.replace(hu,"");return t||"#"!==e.name[0]&&(t="default"),lu.test(t)?{name:t.slice(1,-1),dynamic:!0}:{name:'"'+t+'"',dynamic:!1}}function Co(e){"slot"===e.tag&&(e.slotName=Xn(e,"name"))}function ko(e){var t;(t=Xn(e,"is"))&&(e.component=t),null!=Wn(e,"inline-template")&&(e.inlineTemplate=!0)}function To(e){var t,n,r,o,i,a,s,c,u=e.attrsList;for(t=0,n=u.length;t<n;t++)if(r=o=u[t].name,i=u[t].value,su.test(r))if(e.hasBindings=!0,a=Oo(r.replace(su,"")),a&&(r=r.replace(vu,"")),du.test(r))r=r.replace(du,""),i=Rn(i),c=lu.test(r),c&&(r=r.slice(1,-1)),a&&(a.prop&&!c&&"innerHtml"===(r=Ei(r))&&(r="innerHTML"),a.camel&&!c&&(r=Ei(r)),a.sync&&(s=Qn(i,"$event"),c?Kn(e,'"update:"+('+r+")",s,null,!1,xc,u[t],!0):(Kn(e,"update:"+Ei(r),s,null,!1,xc,u[t]),Li(r)!==Ei(r)&&Kn(e,"update:"+Li(r),s,null,!1,xc,u[t])))),a&&a.prop||!e.component&&Sc(e.tag,e.attrsMap.type,r)?Un(e,r,i,u[t],c):Hn(e,r,i,u[t],c);else if(au.test(r))r=r.replace(au,""),c=lu.test(r),c&&(r=r.slice(1,-1)),Kn(e,r,i,a,!1,xc,u[t],c);else{r=r.replace(su,"");var f=r.match(pu),l=f&&f[1];c=!1,l&&(r=r.slice(0,-(l.length+1)),lu.test(l)&&(l=l.slice(1,-1),c=!0)),zn(e,r,o,i,l,c,a,u[t])}else Hn(e,r,JSON.stringify(i),u[t]),!e.component&&"muted"===r&&Sc(e.tag,e.attrsMap.type,r)&&Un(e,r,"true",u[t])}function So(e){for(var t=e;t;){if(void 0!==t.for)return!0;t=t.parent}return!1}function Oo(e){var t=e.match(vu);if(t){var n={};return t.forEach(function(e){n[e.slice(1)]=!0}),n}}function Eo(e){for(var t={},n=0,r=e.length;n<r;n++)t[e[n].name]=e[n].value;return t}function jo(e){return"script"===e.tag||"style"===e.tag}function Io(e){return"style"===e.tag||"script"===e.tag&&(!e.attrsMap.type||"text/javascript"===e.attrsMap.type)}function Lo(e){for(var t=[],n=0;n<e.length;n++){var r=e[n];_u.test(r.name)||(r.name=r.name.replace(wu,""),t.push(r))}return t}function No(e,t){if("input"===e.tag){var n=e.attrsMap;if(!n["v-model"])return;var r;if((n[":type"]||n["v-bind:type"])&&(r=Xn(e,"type")),n.type||r||!n["v-bind"]||(r="("+n["v-bind"]+").type"),r){var o=Wn(e,"v-if",!0),i=o?"&&("+o+")":"",a=null!=Wn(e,"v-else",!0),s=Wn(e,"v-else-if",!0),c=Do(e);mo(c),qn(c,"type","checkbox"),po(c,t),c.processed=!0,c.if="("+r+")==='checkbox'"+i,wo(c,{exp:c.if,block:c});var u=Do(e);Wn(u,"v-for",!0),qn(u,"type","radio"),po(u,t),wo(c,{exp:"("+r+")==='radio'"+i,block:u});var f=Do(e);return Wn(f,"v-for",!0),qn(f,":type",r),po(f,t),wo(c,{exp:o,block:f}),a?c.else=!0:s&&(c.elseif=s),c}}}function Do(e){return co(e.tag,e.attrsList.slice(),e.parent)}function Po(e,t){t.value&&Un(e,"textContent","_s("+t.value+")",t)}function Ro(e,t){t.value&&Un(e,"innerHTML","_s("+t.value+")",t)}function Mo(e,t){e&&(jc=ku(t.staticKeys||""),Ic=t.isReservedTag||Di,Fo(e),Uo(e,!1))}function Bo(e){return h("type,tag,attrsList,attrsMap,plain,parent,children,attrs,start,end,rawAttrsMap"+(e?","+e:""))}function Fo(e){if(e.static=Ho(e),1===e.type){if(!Ic(e.tag)&&"slot"!==e.tag&&null==e.attrsMap["inline-template"])return;for(var t=0,n=e.children.length;t<n;t++){var r=e.children[t];Fo(r),r.static||(e.static=!1)}if(e.ifConditions)for(var o=1,i=e.ifConditions.length;o<i;o++){var a=e.ifConditions[o].block;Fo(a),a.static||(e.static=!1)}}}function Uo(e,t){if(1===e.type){if((e.static||e.once)&&(e.staticInFor=t),e.static&&e.children.length&&(1!==e.children.length||3!==e.children[0].type))return void(e.staticRoot=!0);if(e.staticRoot=!1,e.children)for(var n=0,r=e.children.length;n<r;n++)Uo(e.children[n],t||!!e.for);if(e.ifConditions)for(var o=1,i=e.ifConditions.length;o<i;o++)Uo(e.ifConditions[o].block,t)}}function Ho(e){return 2!==e.type&&(3===e.type||!(!e.pre&&(e.hasBindings||e.if||e.for||ki(e.tag)||!Ic(e.tag)||qo(e)||!Object.keys(e).every(jc))))}function qo(e){for(;e.parent;){if(e=e.parent,"template"!==e.tag)return!1;if(e.for)return!0}return!1}function zo(e,t){var n=t?"nativeOn:":"on:",r="",o="";for(var i in e){var a=Vo(e[i]);e[i]&&e[i].dynamic?o+=i+","+a+",":r+='"'+i+'":'+a+","}return r="{"+r.slice(0,-1)+"}",o?n+"_d("+r+",["+o.slice(0,-1)+"])":n+r}function Vo(e){if(!e)return"function(){}";if(Array.isArray(e))return"["+e.map(function(e){return Vo(e)}).join(",")+"]";var t=Ou.test(e.value),n=Tu.test(e.value),r=Ou.test(e.value.replace(Su,""));if(e.modifiers){var o="",i="",a=[];for(var s in e.modifiers)if(Lu[s])i+=Lu[s],Eu[s]&&a.push(s);else if("exact"===s){var c=e.modifiers;i+=Iu(["ctrl","shift","alt","meta"].filter(function(e){return!c[e]}).map(function(e){return"$event."+e+"Key"}).join("||"))}else a.push(s);return a.length&&(o+=Ko(a)),i&&(o+=i),"function($event){"+o+(t?"return "+e.value+"($event)":n?"return ("+e.value+")($event)":r?"return "+e.value:e.value)+"}"}return t||n?e.value:"function($event){"+(r?"return "+e.value:e.value)+"}"}function Ko(e){return"if(!$event.type.indexOf('key')&&"+e.map(Jo).join("&&")+")return null;"}function Jo(e){var t=parseInt(e,10);if(t)return"$event.keyCode!=="+t;var n=Eu[e],r=ju[e];return"_k($event.keyCode,"+JSON.stringify(e)+","+JSON.stringify(n)+",$event.key,"+JSON.stringify(r)+")"}function Xo(e,t){e.wrapListeners=function(e){return"_g("+e+","+t.value+")"}}function Wo(e,t){e.wrapData=function(n){return"_b("+n+",'"+e.tag+"',"+t.value+","+(t.modifiers&&t.modifiers.prop?"true":"false")+(t.modifiers&&t.modifiers.sync?",true":"")+")"}}function Go(e,t){var n=new Du(t);return{render:"with(this){return "+(e?Zo(e,n):'_c("div")')+"}",staticRenderFns:n.staticRenderFns}}function Zo(e,t){if(e.parent&&(e.pre=e.pre||e.parent.pre),e.staticRoot&&!e.staticProcessed)return Yo(e,t);if(e.once&&!e.onceProcessed)return Qo(e,t);if(e.for&&!e.forProcessed)return ni(e,t);if(e.if&&!e.ifProcessed)return ei(e,t);if("template"!==e.tag||e.slotTarget||t.pre){if("slot"===e.tag)return mi(e,t);var n;if(e.component)n=yi(e.component,e,t);else{var r;(!e.plain||e.pre&&t.maybeComponent(e))&&(r=ri(e,t));var o=e.inlineTemplate?null:fi(e,t,!0);n="_c('"+e.tag+"'"+(r?","+r:"")+(o?","+o:"")+")"}for(var i=0;i<t.transforms.length;i++)n=t.transforms[i](e,n);return n}return fi(e,t)||"void 0"}function Yo(e,t){e.staticProcessed=!0;var n=t.pre;return e.pre&&(t.pre=e.pre),t.staticRenderFns.push("with(this){return "+Zo(e,t)+"}"),t.pre=n,"_m("+(t.staticRenderFns.length-1)+(e.staticInFor?",true":"")+")"}function Qo(e,t){if(e.onceProcessed=!0,e.if&&!e.ifProcessed)return ei(e,t);if(e.staticInFor){for(var n="",r=e.parent;r;){if(r.for){n=r.key;break}r=r.parent}return n?"_o("+Zo(e,t)+","+t.onceId+++","+n+")":Zo(e,t)}return Yo(e,t)}function ei(e,t,n,r){return e.ifProcessed=!0,ti(e.ifConditions.slice(),t,n,r)}function ti(e,t,n,r){function o(e){return n?n(e,t):e.once?Qo(e,t):Zo(e,t)}if(!e.length)return r||"_e()";var i=e.shift();return i.exp?"("+i.exp+")?"+o(i.block)+":"+ti(e,t,n,r):""+o(i.block)}function ni(e,t,n,r){var o=e.for,i=e.alias,a=e.iterator1?","+e.iterator1:"",s=e.iterator2?","+e.iterator2:"";return e.forProcessed=!0,(r||"_l")+"(("+o+"),function("+i+a+s+"){return "+(n||Zo)(e,t)+"})"}function ri(e,t){var n="{",r=oi(e,t);r&&(n+=r+","),e.key&&(n+="key:"+e.key+","),e.ref&&(n+="ref:"+e.ref+","),e.refInFor&&(n+="refInFor:true,"),e.pre&&(n+="pre:true,"),e.component&&(n+='tag:"'+e.tag+'",');for(var o=0;o<t.dataGenFns.length;o++)n+=t.dataGenFns[o](e);if(e.attrs&&(n+="attrs:"+gi(e.attrs)+","),e.props&&(n+="domProps:"+gi(e.props)+","),e.events&&(n+=zo(e.events,!1)+","),e.nativeEvents&&(n+=zo(e.nativeEvents,!0)+","),e.slotTarget&&!e.slotScope&&(n+="slot:"+e.slotTarget+","),e.scopedSlots&&(n+=ai(e,e.scopedSlots,t)+","),e.model&&(n+="model:{value:"+e.model.value+",callback:"+e.model.callback+",expression:"+e.model.expression+"},"),e.inlineTemplate){var i=ii(e,t);i&&(n+=i+",")}return n=n.replace(/,$/,"")+"}",e.dynamicAttrs&&(n="_b("+n+',"'+e.tag+'",'+gi(e.dynamicAttrs)+")"),e.wrapData&&(n=e.wrapData(n)),e.wrapListeners&&(n=e.wrapListeners(n)),n}function oi(e,t){var n=e.directives;if(n){var r,o,i,a,s="directives:[",c=!1;for(r=0,o=n.length;r<o;r++){i=n[r],a=!0;var u=t.directives[i.name];u&&(a=!!u(e,i,t.warn)),a&&(c=!0,s+='{name:"'+i.name+'",rawName:"'+i.rawName+'"'+(i.value?",value:("+i.value+"),expression:"+JSON.stringify(i.value):"")+(i.arg?",arg:"+(i.isDynamicArg?i.arg:'"'+i.arg+'"'):"")+(i.modifiers?",modifiers:"+JSON.stringify(i.modifiers):"")+"},")}return c?s.slice(0,-1)+"]":void 0}}function ii(e,t){var n=e.children[0];if(n&&1===n.type){var r=Go(n,t.options);return"inlineTemplate:{render:function(){"+r.render+"},staticRenderFns:["+r.staticRenderFns.map(function(e){return"function(){"+e+"}"}).join(",")+"]}"}}function ai(e,t,n){var r=Object.keys(t).some(function(e){var n=t[e];return n.slotTargetDynamic||n.if||n.for||ci(n)}),o=!!e.if;if(!r)for(var i=e.parent;i;){if(i.slotScope&&i.slotScope!==bu||i.for){r=!0;break}i.if&&(o=!0),i=i.parent}var a=Object.keys(t).map(function(e){return ui(t[e],n)}).join(",");return"scopedSlots:_u(["+a+"]"+(r?",null,true":"")+(!r&&o?",null,false,"+si(a):"")+")"}function si(e){for(var t=5381,n=e.length;n;)t=33*t^e.charCodeAt(--n);return t>>>0}function ci(e){return 1===e.type&&("slot"===e.tag||e.children.some(ci))}function ui(e,t){var n=e.attrsMap["slot-scope"];if(e.if&&!e.ifProcessed&&!n)return ei(e,t,ui,"null");if(e.for&&!e.forProcessed)return ni(e,t,ui);var r=e.slotScope===bu?"":String(e.slotScope),o="function("+r+"){return "+("template"===e.tag?e.if&&n?"("+e.if+")?"+(fi(e,t)||"undefined")+":undefined":fi(e,t)||"undefined":Zo(e,t))+"}",i=r?"":",proxy:true";return"{key:"+(e.slotTarget||'"default"')+",fn:"+o+i+"}"}function fi(e,t,n,r,o){var i=e.children;if(i.length){var a=i[0];if(1===i.length&&a.for&&"template"!==a.tag&&"slot"!==a.tag){var s=n?t.maybeComponent(a)?",1":",0":"";return""+(r||Zo)(a,t)+s}var c=n?li(i,t.maybeComponent):0,u=o||di;return"["+i.map(function(e){return u(e,t)}).join(",")+"]"+(c?","+c:"")}}function li(e,t){for(var n=0,r=0;r<e.length;r++){var o=e[r];if(1===o.type){if(pi(o)||o.ifConditions&&o.ifConditions.some(function(e){return pi(e.block)})){n=2;break}(t(o)||o.ifConditions&&o.ifConditions.some(function(e){return t(e.block)}))&&(n=1)}}return n}function pi(e){return void 0!==e.for||"template"===e.tag||"slot"===e.tag}function di(e,t){return 1===e.type?Zo(e,t):3===e.type&&e.isComment?hi(e):vi(e)}function vi(e){return"_v("+(2===e.type?e.expression:bi(JSON.stringify(e.text)))+")"}function hi(e){return"_e("+JSON.stringify(e.text)+")"}function mi(e,t){var n=e.slotName||'"default"',r=fi(e,t),o="_t("+n+(r?","+r:""),i=e.attrs||e.dynamicAttrs?gi((e.attrs||[]).concat(e.dynamicAttrs||[]).map(function(e){return{name:Ei(e.name),value:e.value,dynamic:e.dynamic}})):null,a=e.attrsMap["v-bind"];return!i&&!a||r||(o+=",null"),i&&(o+=","+i),a&&(o+=(i?"":",null")+","+a),o+")"}function yi(e,t,n){var r=t.inlineTemplate?null:fi(t,n,!0);return"_c("+e+","+ri(t,n)+(r?","+r:"")+")"}function gi(e){for(var t="",n="",r=0;r<e.length;r++){var o=e[r],i=bi(o.value);o.dynamic?n+=o.name+","+i+",":t+='"'+o.name+'":'+i+","}return t="{"+t.slice(0,-1)+"}",n?"_d("+t+",["+n.slice(0,-1)+"])":t}function bi(e){return e.replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}function _i(e,t){try{return new Function(e)}catch(n){return t.push({err:n,code:e}),A}}function wi(e){var t=Object.create(null);return function(n,r,o){r=x({},r),r.warn,delete r.warn;var i=r.delimiters?String(r.delimiters)+n:n;if(t[i])return t[i];var a=e(n,r),s={},c=[];return s.render=_i(a.render,c),s.staticRenderFns=a.staticRenderFns.map(function(e){return _i(e,c)}),t[i]=s}}function xi(e){return Lc=Lc||document.createElement("div"),Lc.innerHTML=e?'<a href="\n"/>':'<div a="\n"/>',Lc.innerHTML.indexOf(" ")>0}function $i(e){if(e.outerHTML)return e.outerHTML;var t=document.createElement("div");return t.appendChild(e.cloneNode(!0)),t.innerHTML}/*!
|
2 |
+
* Vue.js v2.6.7
|
3 |
+
* (c) 2014-2019 Evan You
|
4 |
+
* Released under the MIT License.
|
5 |
+
*/
|
6 |
+
var Ai=Object.freeze({}),Ci=Object.prototype.toString,ki=h("slot,component",!0),Ti=h("key,ref,slot,slot-scope,is"),Si=Object.prototype.hasOwnProperty,Oi=/-(\w)/g,Ei=g(function(e){return e.replace(Oi,function(e,t){return t?t.toUpperCase():""})}),ji=g(function(e){return e.charAt(0).toUpperCase()+e.slice(1)}),Ii=/\B([A-Z])/g,Li=g(function(e){return e.replace(Ii,"-$1").toLowerCase()}),Ni=Function.prototype.bind?_:b,Di=function(e,t,n){return!1},Pi=function(e){return e},Ri="data-server-rendered",Mi=["component","directive","filter"],Bi=["beforeCreate","created","beforeMount","mounted","beforeUpdate","updated","beforeDestroy","destroyed","activated","deactivated","errorCaptured","serverPrefetch"],Fi={optionMergeStrategies:Object.create(null),silent:!1,productionTip:!1,devtools:!1,performance:!1,errorHandler:null,warnHandler:null,ignoredElements:[],keyCodes:Object.create(null),isReservedTag:Di,isReservedAttr:Di,isUnknownElement:Di,getTagNamespace:A,parsePlatformTagName:Pi,mustUseProp:Di,async:!0,_lifecycleHooks:Bi},Ui="a-zA-Z·À-ÖØ-öø-ͽͿ--‿-⁀⁰-Ⰰ-、-豈-﷏ﷰ-�",Hi=new RegExp("[^"+Ui+".$_\\d]"),qi="__proto__"in{},zi="undefined"!=typeof window,Vi="undefined"!=typeof WXEnvironment&&!!WXEnvironment.platform,Ki=Vi&&WXEnvironment.platform.toLowerCase(),Ji=zi&&window.navigator.userAgent.toLowerCase(),Xi=Ji&&/msie|trident/.test(Ji),Wi=Ji&&Ji.indexOf("msie 9.0")>0,Gi=Ji&&Ji.indexOf("edge/")>0,Zi=(Ji&&Ji.indexOf("android"),Ji&&/iphone|ipad|ipod|ios/.test(Ji)||"ios"===Ki),Yi=(Ji&&/chrome\/\d+/.test(Ji),Ji&&/phantomjs/.test(Ji),Ji&&Ji.match(/firefox\/(\d+)/)),Qi={}.watch,ea=!1;if(zi)try{var ta={};Object.defineProperty(ta,"passive",{get:function(){ea=!0}}),window.addEventListener("test-passive",null,ta)}catch(e){}var na,ra,oa=function(){return void 0===na&&(na=!zi&&!Vi&&void 0!==e&&e.process&&"server"===e.process.env.VUE_ENV),na},ia=zi&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,aa="undefined"!=typeof Symbol&&j(Symbol)&&"undefined"!=typeof Reflect&&j(Reflect.ownKeys);ra="undefined"!=typeof Set&&j(Set)?Set:function(){function e(){this.set=Object.create(null)}return e.prototype.has=function(e){return!0===this.set[e]},e.prototype.add=function(e){this.set[e]=!0},e.prototype.clear=function(){this.set=Object.create(null)},e}();var sa=A,ca=0,ua=function(){this.id=ca++,this.subs=[]};ua.prototype.addSub=function(e){this.subs.push(e)},ua.prototype.removeSub=function(e){m(this.subs,e)},ua.prototype.depend=function(){ua.target&&ua.target.addDep(this)},ua.prototype.notify=function(){for(var e=this.subs.slice(),t=0,n=e.length;t<n;t++)e[t].update()},ua.target=null;var fa=[],la=function(e,t,n,r,o,i,a,s){this.tag=e,this.data=t,this.children=n,this.text=r,this.elm=o,this.ns=void 0,this.context=i,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=t&&t.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=s,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1},pa={child:{configurable:!0}};pa.child.get=function(){return this.componentInstance},Object.defineProperties(la.prototype,pa);var da=function(e){void 0===e&&(e="");var t=new la;return t.text=e,t.isComment=!0,t},va=Array.prototype,ha=Object.create(va);["push","pop","shift","unshift","splice","sort","reverse"].forEach(function(e){var t=va[e];O(ha,e,function(){for(var n=[],r=arguments.length;r--;)n[r]=arguments[r];var o,i=t.apply(this,n),a=this.__ob__;switch(e){case"push":case"unshift":o=n;break;case"splice":o=n.slice(2)}return o&&a.observeArray(o),a.dep.notify(),i})});var ma=Object.getOwnPropertyNames(ha),ya=!0,ga=function(e){this.value=e,this.dep=new ua,this.vmCount=0,O(e,"__ob__",this),Array.isArray(e)?(qi?R(e,ha):M(e,ha,ma),this.observeArray(e)):this.walk(e)};ga.prototype.walk=function(e){for(var t=Object.keys(e),n=0;n<t.length;n++)F(e,t[n])},ga.prototype.observeArray=function(e){for(var t=0,n=e.length;t<n;t++)B(e[t])};var ba=Fi.optionMergeStrategies;ba.data=function(e,t,n){return n?V(e,t,n):t&&"function"!=typeof t?e:V(e,t)},Bi.forEach(function(e){ba[e]=K}),Mi.forEach(function(e){ba[e+"s"]=X}),ba.watch=function(e,t,n,r){if(e===Qi&&(e=void 0),t===Qi&&(t=void 0),!t)return Object.create(e||null);if(!e)return t;var o={};x(o,e);for(var i in t){var a=o[i],s=t[i];a&&!Array.isArray(a)&&(a=[a]),o[i]=a?a.concat(s):Array.isArray(s)?s:[s]}return o},ba.props=ba.methods=ba.inject=ba.computed=function(e,t,n,r){if(!e)return t;var o=Object.create(null);return x(o,e),t&&x(o,t),o},ba.provide=V;var _a,wa=function(e,t){return void 0===t?e:t},xa=!1,$a=[],Aa=!1;if("undefined"!=typeof Promise&&j(Promise)){var Ca=Promise.resolve();_a=function(){Ca.then(ue),Zi&&setTimeout(A)},xa=!0}else if(Xi||"undefined"==typeof MutationObserver||!j(MutationObserver)&&"[object MutationObserverConstructor]"!==MutationObserver.toString())_a=void 0!==n&&j(n)?function(){n(ue)}:function(){setTimeout(ue,0)};else{var ka=1,Ta=new MutationObserver(ue),Sa=document.createTextNode(String(ka));Ta.observe(Sa,{characterData:!0}),_a=function(){ka=(ka+1)%2,Sa.data=String(ka)},xa=!0}var Oa=new ra,Ea=g(function(e){var t="&"===e.charAt(0);e=t?e.slice(1):e;var n="~"===e.charAt(0);e=n?e.slice(1):e;var r="!"===e.charAt(0);return e=r?e.slice(1):e,{name:e,once:n,capture:r,passive:t}});ze(Ve.prototype);var ja,Ia={init:function(e,t){if(e.componentInstance&&!e.componentInstance._isDestroyed&&e.data.keepAlive){var n=e;Ia.prepatch(n,n)}else(e.componentInstance=Ge(e,Ra)).$mount(t?e.elm:void 0,t)},prepatch:function(e,t){var n=t.componentOptions;gt(t.componentInstance=e.componentInstance,n.propsData,n.listeners,t,n.children)},insert:function(e){var t=e.context,n=e.componentInstance;n._isMounted||(n._isMounted=!0,xt(n,"mounted")),e.data.keepAlive&&(t._isMounted?kt(n):_t(n,!0))},destroy:function(e){var t=e.componentInstance;t._isDestroyed||(e.data.keepAlive?wt(t,!0):t.$destroy())}},La=Object.keys(Ia),Na=1,Da=2,Pa=null,Ra=null,Ma=[],Ba=[],Fa={},Ua=!1,Ha=!1,qa=0,za=0,Va=Date.now;zi&&Va()>document.createEvent("Event").timeStamp&&(Va=function(){return performance.now()});var Ka=0,Ja=function(e,t,n,r,o){this.vm=e,o&&(e._watcher=this),e._watchers.push(this),r?(this.deep=!!r.deep,this.user=!!r.user,this.lazy=!!r.lazy,this.sync=!!r.sync,this.before=r.before):this.deep=this.user=this.lazy=this.sync=!1,this.cb=n,this.id=++Ka,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=new ra,this.newDepIds=new ra,this.expression="","function"==typeof t?this.getter=t:(this.getter=E(t),this.getter||(this.getter=A)),this.value=this.lazy?void 0:this.get()};Ja.prototype.get=function(){I(this);var e,t=this.vm;try{e=this.getter.call(t,t)}catch(e){if(!this.user)throw e;ie(e,t,'getter for watcher "'+this.expression+'"')}finally{this.deep&&le(e),L(),this.cleanupDeps()}return e},Ja.prototype.addDep=function(e){var t=e.id;this.newDepIds.has(t)||(this.newDepIds.add(t),this.newDeps.push(e),this.depIds.has(t)||e.addSub(this))},Ja.prototype.cleanupDeps=function(){for(var e=this.deps.length;e--;){var t=this.deps[e];this.newDepIds.has(t.id)||t.removeSub(this)}var n=this.depIds;this.depIds=this.newDepIds,this.newDepIds=n,this.newDepIds.clear(),n=this.deps,this.deps=this.newDeps,this.newDeps=n,this.newDeps.length=0},Ja.prototype.update=function(){this.lazy?this.dirty=!0:this.sync?this.run():St(this)},Ja.prototype.run=function(){if(this.active){var e=this.get();if(e!==this.value||c(e)||this.deep){var t=this.value;if(this.value=e,this.user)try{this.cb.call(this.vm,e,t)}catch(e){ie(e,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,e,t)}}},Ja.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},Ja.prototype.depend=function(){for(var e=this.deps.length;e--;)this.deps[e].depend()},Ja.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||m(this.vm._watchers,this);for(var e=this.deps.length;e--;)this.deps[e].removeSub(this);this.active=!1}};var Xa={enumerable:!0,configurable:!0,get:A,set:A},Wa={lazy:!0},Ga=0;!function(e){e.prototype._init=function(e){var t=this;t._uid=Ga++,t._isVue=!0,e&&e._isComponent?Ut(t,e):t.$options=Y(Ht(t.constructor),e||{},t),t._renderProxy=t,t._self=t,mt(t),ft(t),ot(t),xt(t,"beforeCreate"),$e(t),Et(t),xe(t),xt(t,"created"),t.$options.el&&t.$mount(t.$options.el)}}(zt),function(e){var t={};t.get=function(){return this._data};var n={};n.get=function(){return this._props},Object.defineProperty(e.prototype,"$data",t),Object.defineProperty(e.prototype,"$props",n),e.prototype.$set=U,e.prototype.$delete=H,e.prototype.$watch=function(e,t,n){var r=this;if(u(t))return Ft(r,e,t,n);n=n||{},n.user=!0;var o=new Ja(r,e,t,n);if(n.immediate)try{t.call(r,o.value)}catch(e){ie(e,r,'callback for immediate watcher "'+o.expression+'"')}return function(){o.teardown()}}}(zt),function(e){var t=/^hook:/;e.prototype.$on=function(e,n){var r=this;if(Array.isArray(e))for(var o=0,i=e.length;o<i;o++)r.$on(e[o],n);else(r._events[e]||(r._events[e]=[])).push(n),t.test(e)&&(r._hasHookEvent=!0);return r},e.prototype.$once=function(e,t){function n(){r.$off(e,n),t.apply(r,arguments)}var r=this;return n.fn=t,r.$on(e,n),r},e.prototype.$off=function(e,t){var n=this;if(!arguments.length)return n._events=Object.create(null),n;if(Array.isArray(e)){for(var r=0,o=e.length;r<o;r++)n.$off(e[r],t);return n}var i=n._events[e];if(!i)return n;if(!t)return n._events[e]=null,n;for(var a,s=i.length;s--;)if((a=i[s])===t||a.fn===t){i.splice(s,1);break}return n},e.prototype.$emit=function(e){var t=this,n=t._events[e];if(n){n=n.length>1?w(n):n;for(var r=w(arguments,1),o='event handler for "'+e+'"',i=0,a=n.length;i<a;i++)ae(n[i],t,r,t,o)}return t}}(zt),function(e){e.prototype._update=function(e,t){var n=this,r=n.$el,o=n._vnode,i=ht(n);n._vnode=e,n.$el=o?n.__patch__(o,e):n.__patch__(n.$el,e,t,!1),i(),r&&(r.__vue__=null),n.$el&&(n.$el.__vue__=n),n.$vnode&&n.$parent&&n.$vnode===n.$parent._vnode&&(n.$parent.$el=n.$el)},e.prototype.$forceUpdate=function(){var e=this;e._watcher&&e._watcher.update()},e.prototype.$destroy=function(){var e=this;if(!e._isBeingDestroyed){xt(e,"beforeDestroy"),e._isBeingDestroyed=!0;var t=e.$parent;!t||t._isBeingDestroyed||e.$options.abstract||m(t.$children,e),e._watcher&&e._watcher.teardown();for(var n=e._watchers.length;n--;)e._watchers[n].teardown();e._data.__ob__&&e._data.__ob__.vmCount--,e._isDestroyed=!0,e.__patch__(e._vnode,null),xt(e,"destroyed"),e.$off(),e.$el&&(e.$el.__vue__=null),e.$vnode&&(e.$vnode.parent=null)}}}(zt),function(e){ze(e.prototype),e.prototype.$nextTick=function(e){return fe(e,this)},e.prototype._render=function(){var e=this,t=e.$options,n=t.render,r=t._parentVnode;r&&(e.$scopedSlots=Te(r.data.scopedSlots,e.$slots,e.$scopedSlots)),e.$vnode=r;var o;try{Pa=e,o=n.call(e._renderProxy,e.$createElement)}catch(t){ie(t,e,"render"),o=e._vnode}finally{Pa=null}return Array.isArray(o)&&1===o.length&&(o=o[0]),o instanceof la||(o=da()),o.parent=r,o}}(zt);var Za=[String,RegExp,Array],Ya={name:"keep-alive",abstract:!0,props:{include:Za,exclude:Za,max:[String,Number]},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var e in this.cache)en(this.cache,e,this.keys)},mounted:function(){var e=this;this.$watch("include",function(t){Qt(e,function(e){return Yt(t,e)})}),this.$watch("exclude",function(t){Qt(e,function(e){return!Yt(t,e)})})},render:function(){var e=this.$slots.default,t=ut(e),n=t&&t.componentOptions;if(n){var r=Zt(n),o=this,i=o.include,a=o.exclude;if(i&&(!r||!Yt(i,r))||a&&r&&Yt(a,r))return t;var s=this,c=s.cache,u=s.keys,f=null==t.key?n.Ctor.cid+(n.tag?"::"+n.tag:""):t.key;c[f]?(t.componentInstance=c[f].componentInstance,m(u,f),u.push(f)):(c[f]=t,u.push(f),this.max&&u.length>parseInt(this.max)&&en(c,u[0],u,this._vnode)),t.data.keepAlive=!0}return t||e&&e[0]}},Qa={KeepAlive:Ya};!function(e){var t={};t.get=function(){return Fi},Object.defineProperty(e,"config",t),e.util={warn:sa,extend:x,mergeOptions:Y,defineReactive:F},e.set=U,e.delete=H,e.nextTick=fe,e.observable=function(e){return B(e),e},e.options=Object.create(null),Mi.forEach(function(t){e.options[t+"s"]=Object.create(null)}),e.options._base=e,x(e.options.components,Qa),Vt(e),Kt(e),Jt(e),Gt(e)}(zt),Object.defineProperty(zt.prototype,"$isServer",{get:oa}),Object.defineProperty(zt.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(zt,"FunctionalRenderContext",{value:Ve}),zt.version="2.6.7";var es,ts,ns,rs,os,is,as,ss,cs,us,fs=h("style,class"),ls=h("input,textarea,option,select,progress"),ps=function(e,t,n){return"value"===n&&ls(e)&&"button"!==t||"selected"===n&&"option"===e||"checked"===n&&"input"===e||"muted"===n&&"video"===e},ds=h("contenteditable,draggable,spellcheck"),vs=h("events,caret,typing,plaintext-only"),hs=function(e,t){return _s(t)||"false"===t?"false":"contenteditable"===e&&vs(t)?t:"true"},ms=h("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,translate,truespeed,typemustmatch,visible"),ys="http://www.w3.org/1999/xlink",gs=function(e){return":"===e.charAt(5)&&"xlink"===e.slice(0,5)},bs=function(e){return gs(e)?e.slice(6,e.length):""},_s=function(e){return null==e||!1===e},ws={svg:"http://www.w3.org/2000/svg",math:"http://www.w3.org/1998/Math/MathML"},xs=h("html,body,base,head,link,meta,style,title,address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,menuitem,summary,content,element,shadow,template,blockquote,iframe,tfoot"),$s=h("svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view",!0),As=function(e){return"pre"===e},Cs=function(e){return xs(e)||$s(e)},ks=Object.create(null),Ts=h("text,number,password,search,email,tel,url"),Ss=Object.freeze({createElement:pn,createElementNS:dn,createTextNode:vn,createComment:hn,insertBefore:mn,removeChild:yn,appendChild:gn,parentNode:bn,nextSibling:_n,tagName:wn,setTextContent:xn,setStyleScope:$n}),Os={create:function(e,t){An(t)},update:function(e,t){e.data.ref!==t.data.ref&&(An(e,!0),An(t))},destroy:function(e){An(e,!0)}},Es=new la("",{},[]),js=["create","activate","update","remove","destroy"],Is={create:Sn,update:Sn,destroy:function(e){Sn(e,Es)}},Ls=Object.create(null),Ns=[Os,Is],Ds={create:Ln,update:Ln},Ps={create:Pn,update:Pn},Rs=/[\w).+\-_$\]]/,Ms="__r",Bs="__c",Fs=xa&&!(Yi&&Number(Yi[1])<=53),Us={create:hr,update:hr},Hs={create:mr,update:mr},qs=g(function(e){var t={},n=/;(?![^(]*\))/g,r=/:(.+)/;return e.split(n).forEach(function(e){if(e){var n=e.split(r);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}),zs=/^--/,Vs=/\s*!important$/,Ks=function(e,t,n){if(zs.test(t))e.style.setProperty(t,n);else if(Vs.test(n))e.style.setProperty(Li(t),n.replace(Vs,""),"important");else{var r=Xs(t);if(Array.isArray(n))for(var o=0,i=n.length;o<i;o++)e.style[r]=n[o];else e.style[r]=n}},Js=["Webkit","Moz","ms"],Xs=g(function(e){if(us=us||document.createElement("div").style,"filter"!==(e=Ei(e))&&e in us)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=0;n<Js.length;n++){var r=Js[n]+t;if(r in us)return r}}),Ws={create:$r,update:$r},Gs=/\s+/,Zs=g(function(e){return{enterClass:e+"-enter",enterToClass:e+"-enter-to",enterActiveClass:e+"-enter-active",leaveClass:e+"-leave",leaveToClass:e+"-leave-to",leaveActiveClass:e+"-leave-active"}}),Ys=zi&&!Wi,Qs="transition",ec="animation",tc="transition",nc="transitionend",rc="animation",oc="animationend";Ys&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(tc="WebkitTransition",nc="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(rc="WebkitAnimation",oc="webkitAnimationEnd"));var ic=zi?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(e){return e()},ac=/\b(transform|all)(,|$)/,sc=zi?{create:Mr,activate:Mr,remove:function(e,t){!0!==e.data.show?Dr(e,t):t()}}:{},cc=[Ds,Ps,Us,Hs,Ws,sc],uc=cc.concat(Ns),fc=function(e){function t(e){return new la(j.tagName(e).toLowerCase(),{},[],void 0,e)}function n(e,t){function n(){0==--n.listeners&&a(e)}return n.listeners=t,n}function a(e){var t=j.parentNode(e);o(t)&&j.removeChild(t,e)}function c(e,t,n,r,a,s,c){if(o(e.elm)&&o(s)&&(e=s[c]=D(e)),e.isRootInsert=!a,!u(e,t,n,r)){var f=e.data,l=e.children,v=e.tag;o(v)?(e.elm=e.ns?j.createElementNS(e.ns,v):j.createElement(v,e),y(e),d(e,l,t),o(f)&&m(e,t),p(n,e.elm,r)):i(e.isComment)?(e.elm=j.createComment(e.text),p(n,e.elm,r)):(e.elm=j.createTextNode(e.text),p(n,e.elm,r))}}function u(e,t,n,r){var a=e.data;if(o(a)){var s=o(e.componentInstance)&&a.keepAlive;if(o(a=a.hook)&&o(a=a.init)&&a(e,!1),o(e.componentInstance))return f(e,t),p(n,e.elm,r),i(s)&&l(e,t,n,r),!0}}function f(e,t){o(e.data.pendingInsert)&&(t.push.apply(t,e.data.pendingInsert),e.data.pendingInsert=null),e.elm=e.componentInstance.$el,v(e)?(m(e,t),y(e)):(An(e),t.push(e))}function l(e,t,n,r){for(var i,a=e;a.componentInstance;)if(a=a.componentInstance._vnode,o(i=a.data)&&o(i=i.transition)){for(i=0;i<O.activate.length;++i)O.activate[i](Es,a);t.push(a);break}p(n,e.elm,r)}function p(e,t,n){o(e)&&(o(n)?j.parentNode(n)===e&&j.insertBefore(e,t,n):j.appendChild(e,t))}function d(e,t,n){if(Array.isArray(t))for(var r=0;r<t.length;++r)c(t[r],n,e.elm,null,!0,t,r);else s(e.text)&&j.appendChild(e.elm,j.createTextNode(String(e.text)))}function v(e){for(;e.componentInstance;)e=e.componentInstance._vnode;return o(e.tag)}function m(e,t){for(var n=0;n<O.create.length;++n)O.create[n](Es,e);T=e.data.hook,o(T)&&(o(T.create)&&T.create(Es,e),o(T.insert)&&t.push(e))}function y(e){var t;if(o(t=e.fnScopeId))j.setStyleScope(e.elm,t);else for(var n=e;n;)o(t=n.context)&&o(t=t.$options._scopeId)&&j.setStyleScope(e.elm,t),n=n.parent;o(t=Ra)&&t!==e.context&&t!==e.fnContext&&o(t=t.$options._scopeId)&&j.setStyleScope(e.elm,t)}function g(e,t,n,r,o,i){for(;r<=o;++r)c(n[r],i,e,t,!1,n,r)}function b(e){var t,n,r=e.data;if(o(r))for(o(t=r.hook)&&o(t=t.destroy)&&t(e),t=0;t<O.destroy.length;++t)O.destroy[t](e);if(o(t=e.children))for(n=0;n<e.children.length;++n)b(e.children[n])}function _(e,t,n,r){for(;n<=r;++n){var i=t[n];o(i)&&(o(i.tag)?(w(i),b(i)):a(i.elm))}}function w(e,t){if(o(t)||o(e.data)){var r,i=O.remove.length+1;for(o(t)?t.listeners+=i:t=n(e.elm,i),o(r=e.componentInstance)&&o(r=r._vnode)&&o(r.data)&&w(r,t),r=0;r<O.remove.length;++r)O.remove[r](e,t);o(r=e.data.hook)&&o(r=r.remove)?r(e,t):t()}else a(e.elm)}function x(e,t,n,i,a){for(var s,u,f,l,p=0,d=0,v=t.length-1,h=t[0],m=t[v],y=n.length-1,b=n[0],w=n[y],x=!a;p<=v&&d<=y;)r(h)?h=t[++p]:r(m)?m=t[--v]:Cn(h,b)?(A(h,b,i,n,d),h=t[++p],b=n[++d]):Cn(m,w)?(A(m,w,i,n,y),m=t[--v],w=n[--y]):Cn(h,w)?(A(h,w,i,n,y),x&&j.insertBefore(e,h.elm,j.nextSibling(m.elm)),h=t[++p],w=n[--y]):Cn(m,b)?(A(m,b,i,n,d),x&&j.insertBefore(e,m.elm,h.elm),m=t[--v],b=n[++d]):(r(s)&&(s=Tn(t,p,v)),u=o(b.key)?s[b.key]:$(b,t,p,v),r(u)?c(b,i,e,h.elm,!1,n,d):(f=t[u],Cn(f,b)?(A(f,b,i,n,d),t[u]=void 0,x&&j.insertBefore(e,f.elm,h.elm)):c(b,i,e,h.elm,!1,n,d)),b=n[++d]);p>v?(l=r(n[y+1])?null:n[y+1].elm,g(e,l,n,d,y,i)):d>y&&_(e,t,p,v)}function $(e,t,n,r){for(var i=n;i<r;i++){var a=t[i];if(o(a)&&Cn(e,a))return i}}function A(e,t,n,a,s,c){if(e!==t){o(t.elm)&&o(a)&&(t=a[s]=D(t));var u=t.elm=e.elm;if(i(e.isAsyncPlaceholder))return void(o(t.asyncFactory.resolved)?k(e.elm,t,n):t.isAsyncPlaceholder=!0);if(i(t.isStatic)&&i(e.isStatic)&&t.key===e.key&&(i(t.isCloned)||i(t.isOnce)))return void(t.componentInstance=e.componentInstance);var f,l=t.data;o(l)&&o(f=l.hook)&&o(f=f.prepatch)&&f(e,t);var p=e.children,d=t.children;if(o(l)&&v(t)){for(f=0;f<O.update.length;++f)O.update[f](e,t);o(f=l.hook)&&o(f=f.update)&&f(e,t)}r(t.text)?o(p)&&o(d)?p!==d&&x(u,p,d,n,c):o(d)?(o(e.text)&&j.setTextContent(u,""),g(u,null,d,0,d.length-1,n)):o(p)?_(u,p,0,p.length-1):o(e.text)&&j.setTextContent(u,""):e.text!==t.text&&j.setTextContent(u,t.text),o(l)&&o(f=l.hook)&&o(f=f.postpatch)&&f(e,t)}}function C(e,t,n){if(i(n)&&o(e.parent))e.parent.data.pendingInsert=t;else for(var r=0;r<t.length;++r)t[r].data.hook.insert(t[r])}function k(e,t,n,r){var a,s=t.tag,c=t.data,u=t.children;if(r=r||c&&c.pre,t.elm=e,i(t.isComment)&&o(t.asyncFactory))return t.isAsyncPlaceholder=!0,!0;if(o(c)&&(o(a=c.hook)&&o(a=a.init)&&a(t,!0),o(a=t.componentInstance)))return f(t,n),!0;if(o(s)){if(o(u))if(e.hasChildNodes())if(o(a=c)&&o(a=a.domProps)&&o(a=a.innerHTML)){if(a!==e.innerHTML)return!1}else{for(var l=!0,p=e.firstChild,v=0;v<u.length;v++){if(!p||!k(p,u[v],n,r)){l=!1;break}p=p.nextSibling}if(!l||p)return!1}else d(t,u,n);if(o(c)){var h=!1;for(var y in c)if(!I(y)){h=!0,m(t,n);break}!h&&c.class&&le(c.class)}}else e.data!==t.text&&(e.data=t.text);return!0}var T,S,O={},E=e.modules,j=e.nodeOps;for(T=0;T<js.length;++T)for(O[js[T]]=[],S=0;S<E.length;++S)o(E[S][js[T]])&&O[js[T]].push(E[S][js[T]]);var I=h("attrs,class,staticClass,staticStyle,key");return function(e,n,a,s){if(r(n))return void(o(e)&&b(e));var u=!1,f=[];if(r(e))u=!0,c(n,f);else{var l=o(e.nodeType);if(!l&&Cn(e,n))A(e,n,f,null,null,s);else{if(l){if(1===e.nodeType&&e.hasAttribute(Ri)&&(e.removeAttribute(Ri),a=!0),i(a)&&k(e,n,f))return C(n,f,!0),e;e=t(e)}var p=e.elm,d=j.parentNode(p);if(c(n,f,p._leaveCb?null:d,j.nextSibling(p)),o(n.parent))for(var h=n.parent,m=v(n);h;){for(var y=0;y<O.destroy.length;++y)O.destroy[y](h);if(h.elm=n.elm,m){for(var g=0;g<O.create.length;++g)O.create[g](Es,h);var w=h.data.hook.insert;if(w.merged)for(var x=1;x<w.fns.length;x++)w.fns[x]()}else An(h);h=h.parent}o(d)?_(d,[e],0,0):o(e.tag)&&b(e)}}return C(n,f,u),n.elm}}({nodeOps:Ss,modules:uc});Wi&&document.addEventListener("selectionchange",function(){var e=document.activeElement;e&&e.vmodel&&Vr(e,"input")});var lc={inserted:function(e,t,n,r){"select"===n.tag?(r.elm&&!r.elm._vOptions?he(n,"postpatch",function(){lc.componentUpdated(e,t,n)}):Br(e,t,n.context),e._vOptions=[].map.call(e.options,Hr)):("textarea"===n.tag||Ts(e.type))&&(e._vModifiers=t.modifiers,t.modifiers.lazy||(e.addEventListener("compositionstart",qr),e.addEventListener("compositionend",zr),e.addEventListener("change",zr),Wi&&(e.vmodel=!0)))},componentUpdated:function(e,t,n){if("select"===n.tag){Br(e,t,n.context);var r=e._vOptions,o=e._vOptions=[].map.call(e.options,Hr);o.some(function(e,t){return!C(e,r[t])})&&(e.multiple?t.value.some(function(e){return Ur(e,o)}):t.value!==t.oldValue&&Ur(t.value,o))&&Vr(e,"change")}}},pc={bind:function(e,t,n){var r=t.value;n=Kr(n);var o=n.data&&n.data.transition,i=e.__vOriginalDisplay="none"===e.style.display?"":e.style.display;r&&o?(n.data.show=!0,Nr(n,function(){e.style.display=i})):e.style.display=r?i:"none"},update:function(e,t,n){var r=t.value;!r!=!t.oldValue&&(n=Kr(n),n.data&&n.data.transition?(n.data.show=!0,r?Nr(n,function(){e.style.display=e.__vOriginalDisplay}):Dr(n,function(){e.style.display="none"})):e.style.display=r?e.__vOriginalDisplay:"none")},unbind:function(e,t,n,r,o){o||(e.style.display=e.__vOriginalDisplay)}},dc={model:lc,show:pc},vc={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]},hc=function(e){return e.tag||ct(e)},mc=function(e){return"show"===e.name},yc={name:"transition",props:vc,abstract:!0,render:function(e){var t=this,n=this.$slots.default;if(n&&(n=n.filter(hc),n.length)){var r=this.mode,o=n[0];if(Gr(this.$vnode))return o;var i=Jr(o);if(!i)return o;if(this._leaving)return Wr(e,o);var a="__transition-"+this._uid+"-";i.key=null==i.key?i.isComment?a+"comment":a+i.tag:s(i.key)?0===String(i.key).indexOf(a)?i.key:a+i.key:i.key;var c=(i.data||(i.data={})).transition=Xr(this),u=this._vnode,f=Jr(u);if(i.data.directives&&i.data.directives.some(mc)&&(i.data.show=!0),f&&f.data&&!Zr(i,f)&&!ct(f)&&(!f.componentInstance||!f.componentInstance._vnode.isComment)){var l=f.data.transition=x({},c);if("out-in"===r)return this._leaving=!0,he(l,"afterLeave",function(){t._leaving=!1,t.$forceUpdate()}),Wr(e,o);if("in-out"===r){if(ct(i))return u;var p,d=function(){p()};he(c,"afterEnter",d),he(c,"enterCancelled",d),he(l,"delayLeave",function(e){p=e})}}return o}}},gc=x({tag:String,moveClass:String},vc);delete gc.mode;var bc={props:gc,beforeMount:function(){var e=this,t=this._update;this._update=function(n,r){var o=ht(e);e.__patch__(e._vnode,e.kept,!1,!0),e._vnode=e.kept,o(),t.call(e,n,r)}},render:function(e){for(var t=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,o=this.$slots.default||[],i=this.children=[],a=Xr(this),s=0;s<o.length;s++){var c=o[s];c.tag&&null!=c.key&&0!==String(c.key).indexOf("__vlist")&&(i.push(c),n[c.key]=c,(c.data||(c.data={})).transition=a)}if(r){for(var u=[],f=[],l=0;l<r.length;l++){var p=r[l];p.data.transition=a,p.data.pos=p.elm.getBoundingClientRect(),n[p.key]?u.push(p):f.push(p)}this.kept=e(t,null,u),this.removed=f}return e(t,null,i)},updated:function(){var e=this.prevChildren,t=this.moveClass||(this.name||"v")+"-move";e.length&&this.hasMove(e[0].elm,t)&&(e.forEach(Yr),e.forEach(Qr),e.forEach(eo),this._reflow=document.body.offsetHeight,e.forEach(function(e){if(e.data.moved){var n=e.elm,r=n.style;Sr(n,t),r.transform=r.WebkitTransform=r.transitionDuration="",n.addEventListener(nc,n._moveCb=function e(r){r&&r.target!==n||r&&!/transform$/.test(r.propertyName)||(n.removeEventListener(nc,e),n._moveCb=null,Or(n,t))})}}))},methods:{hasMove:function(e,t){if(!Ys)return!1;if(this._hasMove)return this._hasMove;var n=e.cloneNode();e._transitionClasses&&e._transitionClasses.forEach(function(e){Cr(n,e)}),Ar(n,t),n.style.display="none",this.$el.appendChild(n);var r=jr(n);return this.$el.removeChild(n),this._hasMove=r.hasTransform}}},_c={Transition:yc,TransitionGroup:bc};zt.config.mustUseProp=ps,zt.config.isReservedTag=Cs,zt.config.isReservedAttr=fs,zt.config.getTagNamespace=un,zt.config.isUnknownElement=fn,x(zt.options.directives,dc),x(zt.options.components,_c),zt.prototype.__patch__=zi?fc:A,zt.prototype.$mount=function(e,t){return e=e&&zi?ln(e):void 0,yt(this,e,t)},zi&&setTimeout(function(){Fi.devtools&&ia&&ia.emit("init",zt)},0);var wc,xc,$c,Ac,Cc,kc,Tc,Sc,Oc,Ec,jc,Ic,Lc,Nc=/\{\{((?:.|\r?\n)+?)\}\}/g,Dc=/[-.*+?^${}()|[\]\/\\]/g,Pc=g(function(e){var t=e[0].replace(Dc,"\\$&"),n=e[1].replace(Dc,"\\$&");return new RegExp(t+"((?:.|\\n)+?)"+n,"g")}),Rc={staticKeys:["staticClass"],transformNode:no,genData:ro},Mc={staticKeys:["staticStyle"],transformNode:oo,genData:io},Bc={decode:function(e){return wc=wc||document.createElement("div"),wc.innerHTML=e,wc.textContent}},Fc=h("area,base,br,col,embed,frame,hr,img,input,isindex,keygen,link,meta,param,source,track,wbr"),Uc=h("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source"),Hc=h("address,article,aside,base,blockquote,body,caption,col,colgroup,dd,details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,title,tr,track"),qc=/^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,zc=/^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,Vc="[a-zA-Z_][\\-\\.0-9_a-zA-Z"+Ui+"]*",Kc="((?:"+Vc+"\\:)?"+Vc+")",Jc=new RegExp("^<"+Kc),Xc=/^\s*(\/?)>/,Wc=new RegExp("^<\\/"+Kc+"[^>]*>"),Gc=/^<!DOCTYPE [^>]+>/i,Zc=/^<!\--/,Yc=/^<!\[/,Qc=h("script,style,textarea",!0),eu={},tu={"<":"<",">":">",""":'"',"&":"&"," ":"\n","	":"\t","'":"'"},nu=/&(?:lt|gt|quot|amp|#39);/g,ru=/&(?:lt|gt|quot|amp|#39|#10|#9);/g,ou=h("pre,textarea",!0),iu=function(e,t){return e&&ou(e)&&"\n"===t[0]},au=/^@|^v-on:/,su=/^v-|^@|^:/,cu=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,uu=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,fu=/^\(|\)$/g,lu=/^\[.*\]$/,pu=/:(.*)$/,du=/^:|^\.|^v-bind:/,vu=/\.[^.]+/g,hu=/^v-slot(:|$)|^#/,mu=/[\r\n]/,yu=/\s+/g,gu=g(Bc.decode),bu="_empty_",_u=/^xmlns:NS\d+/,wu=/^NS\d+:/,xu={preTransformNode:No},$u=[Rc,Mc,xu],Au={model:ar,text:Po,html:Ro},Cu={expectHTML:!0,modules:$u,directives:Au,isPreTag:As,isUnaryTag:Fc,mustUseProp:ps,canBeLeftOpenTag:Uc,isReservedTag:Cs,getTagNamespace:un,staticKeys:function(e){return e.reduce(function(e,t){return e.concat(t.staticKeys||[])},[]).join(",")}($u)},ku=g(Bo),Tu=/^([\w$_]+|\([^)]*?\))\s*=>|^function\s*\(/,Su=/\([^)]*?\);*$/,Ou=/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/,Eu={esc:27,tab:9,enter:13,space:32,up:38,left:37,right:39,down:40,delete:[8,46]},ju={esc:["Esc","Escape"],tab:"Tab",enter:"Enter",space:[" ","Spacebar"],up:["Up","ArrowUp"],left:["Left","ArrowLeft"],right:["Right","ArrowRight"],down:["Down","ArrowDown"],delete:["Backspace","Delete","Del"]},Iu=function(e){return"if("+e+")return null;"},Lu={stop:"$event.stopPropagation();",prevent:"$event.preventDefault();",self:Iu("$event.target !== $event.currentTarget"),ctrl:Iu("!$event.ctrlKey"),shift:Iu("!$event.shiftKey"),alt:Iu("!$event.altKey"),meta:Iu("!$event.metaKey"),left:Iu("'button' in $event && $event.button !== 0"),middle:Iu("'button' in $event && $event.button !== 1"),right:Iu("'button' in $event && $event.button !== 2")},Nu={on:Xo,bind:Wo,cloak:A},Du=function(e){this.options=e,this.warn=e.warn||Bn,this.transforms=Fn(e.modules,"transformCode"),this.dataGenFns=Fn(e.modules,"genData"),this.directives=x(x({},Nu),e.directives);var t=e.isReservedTag||Di;this.maybeComponent=function(e){return!!e.component||!t(e.tag)},this.onceId=0,this.staticRenderFns=[],this.pre=!1},Pu=(new RegExp("\\b"+"do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,super,throw,while,yield,delete,export,import,return,switch,default,extends,finally,continue,debugger,function,arguments".split(",").join("\\b|\\b")+"\\b"),new RegExp("\\b"+"delete,typeof,void".split(",").join("\\s*\\([^\\)]*\\)|\\b")+"\\s*\\([^\\)]*\\)"),function(e){return function(t){function n(n,r){var o=Object.create(t),i=[],a=[],s=function(e,t,n){(n?a:i).push(e)};if(r){r.modules&&(o.modules=(t.modules||[]).concat(r.modules)),r.directives&&(o.directives=x(Object.create(t.directives||null),r.directives));for(var c in r)"modules"!==c&&"directives"!==c&&(o[c]=r[c])}o.warn=s;var u=e(n.trim(),o);return u.errors=i,u.tips=a,u}return{compile:n,compileToFunctions:wi(n)}}}(function(e,t){var n=uo(e.trim(),t);!1!==t.optimize&&Mo(n,t);var r=Go(n,t);return{ast:n,render:r.render,staticRenderFns:r.staticRenderFns}})),Ru=Pu(Cu),Mu=(Ru.compile,Ru.compileToFunctions),Bu=!!zi&&xi(!1),Fu=!!zi&&xi(!0),Uu=g(function(e){var t=ln(e);return t&&t.innerHTML}),Hu=zt.prototype.$mount;zt.prototype.$mount=function(e,t){if((e=e&&ln(e))===document.body||e===document.documentElement)return this;var n=this.$options;if(!n.render){var r=n.template;if(r)if("string"==typeof r)"#"===r.charAt(0)&&(r=Uu(r));else{if(!r.nodeType)return this;r=r.innerHTML}else e&&(r=$i(e));if(r){var o=Mu(r,{outputSourceRange:!1,shouldDecodeNewlines:Bu,shouldDecodeNewlinesForHref:Fu,delimiters:n.delimiters,comments:n.comments},this),i=o.render,a=o.staticRenderFns;n.render=i,n.staticRenderFns=a}}return Hu.call(this,e,t)},zt.compile=Mu,t.a=zt}).call(t,n(2),n(13).setImmediate)},function(e,t){function n(){throw new Error("setTimeout has not been defined")}function r(){throw new Error("clearTimeout has not been defined")}function o(e){if(f===setTimeout)return setTimeout(e,0);if((f===n||!f)&&setTimeout)return f=setTimeout,setTimeout(e,0);try{return f(e,0)}catch(t){try{return f.call(null,e,0)}catch(t){return f.call(this,e,0)}}}function i(e){if(l===clearTimeout)return clearTimeout(e);if((l===r||!l)&&clearTimeout)return l=clearTimeout,clearTimeout(e);try{return l(e)}catch(t){try{return l.call(null,e)}catch(t){return l.call(this,e)}}}function a(){h&&d&&(h=!1,d.length?v=d.concat(v):m=-1,v.length&&s())}function s(){if(!h){var e=o(a);h=!0;for(var t=v.length;t;){for(d=v,v=[];++m<t;)d&&d[m].run();m=-1,t=v.length}d=null,h=!1,i(e)}}function c(e,t){this.fun=e,this.array=t}function u(){}var f,l,p=e.exports={};!function(){try{f="function"==typeof setTimeout?setTimeout:n}catch(e){f=n}try{l="function"==typeof clearTimeout?clearTimeout:r}catch(e){l=r}}();var d,v=[],h=!1,m=-1;p.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];v.push(new c(e,t)),1!==v.length||h||o(s)},c.prototype.run=function(){this.fun.apply(null,this.array)},p.title="browser",p.browser=!0,p.env={},p.argv=[],p.version="",p.versions={},p.on=u,p.addListener=u,p.once=u,p.off=u,p.removeListener=u,p.removeAllListeners=u,p.emit=u,p.prependListener=u,p.prependOnceListener=u,p.listeners=function(e){return[]},p.binding=function(e){throw new Error("process.binding is not supported")},p.cwd=function(){return"/"},p.chdir=function(e){throw new Error("process.chdir is not supported")},p.umask=function(){return 0}},function(e,t,n){"use strict";e.exports=function(e,t){return function(){for(var n=new Array(arguments.length),r=0;r<n.length;r++)n[r]=arguments[r];return e.apply(t,n)}}},function(e,t,n){"use strict";var r=n(0),o=n(23),i=n(25),a=n(26),s=n(27),c=n(8),u="undefined"!=typeof window&&window.btoa&&window.btoa.bind(window)||n(28);e.exports=function(e){return new Promise(function(t,f){var l=e.data,p=e.headers;r.isFormData(l)&&delete p["Content-Type"];var d=new XMLHttpRequest,v="onreadystatechange",h=!1;if("undefined"==typeof window||!window.XDomainRequest||"withCredentials"in d||s(e.url)||(d=new window.XDomainRequest,v="onload",h=!0,d.onprogress=function(){},d.ontimeout=function(){}),e.auth){var m=e.auth.username||"",y=e.auth.password||"";p.Authorization="Basic "+u(m+":"+y)}if(d.open(e.method.toUpperCase(),i(e.url,e.params,e.paramsSerializer),!0),d.timeout=e.timeout,d[v]=function(){if(d&&(4===d.readyState||h)&&(0!==d.status||d.responseURL&&0===d.responseURL.indexOf("file:"))){var n="getAllResponseHeaders"in d?a(d.getAllResponseHeaders()):null,r=e.responseType&&"text"!==e.responseType?d.response:d.responseText,i={data:r,status:1223===d.status?204:d.status,statusText:1223===d.status?"No Content":d.statusText,headers:n,config:e,request:d};o(t,f,i),d=null}},d.onerror=function(){f(c("Network Error",e,null,d)),d=null},d.ontimeout=function(){f(c("timeout of "+e.timeout+"ms exceeded",e,"ECONNABORTED",d)),d=null},r.isStandardBrowserEnv()){var g=n(29),b=(e.withCredentials||s(e.url))&&e.xsrfCookieName?g.read(e.xsrfCookieName):void 0;b&&(p[e.xsrfHeaderName]=b)}if("setRequestHeader"in d&&r.forEach(p,function(e,t){void 0===l&&"content-type"===t.toLowerCase()?delete p[t]:d.setRequestHeader(t,e)}),e.withCredentials&&(d.withCredentials=!0),e.responseType)try{d.responseType=e.responseType}catch(t){if("json"!==e.responseType)throw t}"function"==typeof e.onDownloadProgress&&d.addEventListener("progress",e.onDownloadProgress),"function"==typeof e.onUploadProgress&&d.upload&&d.upload.addEventListener("progress",e.onUploadProgress),e.cancelToken&&e.cancelToken.promise.then(function(e){d&&(d.abort(),f(e),d=null)}),void 0===l&&(l=null),d.send(l)})}},function(e,t,n){"use strict";var r=n(24);e.exports=function(e,t,n,o,i){var a=new Error(e);return r(a,t,n,o,i)}},function(e,t,n){"use strict";e.exports=function(e){return!(!e||!e.__CANCEL__)}},function(e,t,n){"use strict";function r(e){this.message=e}r.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},r.prototype.__CANCEL__=!0,e.exports=r},,,function(e,t,n){(function(e){function r(e,t){this._id=e,this._clearFn=t}var o=void 0!==e&&e||"undefined"!=typeof self&&self||window,i=Function.prototype.apply;t.setTimeout=function(){return new r(i.call(setTimeout,o,arguments),clearTimeout)},t.setInterval=function(){return new r(i.call(setInterval,o,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},r.prototype.unref=r.prototype.ref=function(){},r.prototype.close=function(){this._clearFn.call(o,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout(function(){e._onTimeout&&e._onTimeout()},t))},n(14),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(t,n(2))},function(e,t,n){(function(e,t){!function(e,n){"use strict";function r(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n<t.length;n++)t[n]=arguments[n+1];var r={callback:e,args:t};return u[c]=r,s(c),c++}function o(e){delete u[e]}function i(e){var t=e.callback,r=e.args;switch(r.length){case 0:t();break;case 1:t(r[0]);break;case 2:t(r[0],r[1]);break;case 3:t(r[0],r[1],r[2]);break;default:t.apply(n,r)}}function a(e){if(f)setTimeout(a,0,e);else{var t=u[e];if(t){f=!0;try{i(t)}finally{o(e),f=!1}}}}if(!e.setImmediate){var s,c=1,u={},f=!1,l=e.document,p=Object.getPrototypeOf&&Object.getPrototypeOf(e);p=p&&p.setTimeout?p:e,"[object process]"==={}.toString.call(e.process)?function(){s=function(e){t.nextTick(function(){a(e)})}}():function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}}()?function(){var t="setImmediate$"+Math.random()+"$",n=function(n){n.source===e&&"string"==typeof n.data&&0===n.data.indexOf(t)&&a(+n.data.slice(t.length))};e.addEventListener?e.addEventListener("message",n,!1):e.attachEvent("onmessage",n),s=function(n){e.postMessage(t+n,"*")}}():e.MessageChannel?function(){var e=new MessageChannel;e.port1.onmessage=function(e){a(e.data)},s=function(t){e.port2.postMessage(t)}}():l&&"onreadystatechange"in l.createElement("script")?function(){var e=l.documentElement;s=function(t){var n=l.createElement("script");n.onreadystatechange=function(){a(t),n.onreadystatechange=null,e.removeChild(n),n=null},e.appendChild(n)}}():function(){s=function(e){setTimeout(a,0,e)}}(),p.setImmediate=r,p.clearImmediate=o}}("undefined"==typeof self?void 0===e?this:e:self)}).call(t,n(2),n(5))},function(e,t,n){"use strict";function r(e){return e&&DataView.prototype.isPrototypeOf(e)}function o(e){if("string"!=typeof e&&(e=String(e)),/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(e))throw new TypeError("Invalid character in header field name");return e.toLowerCase()}function i(e){return"string"!=typeof e&&(e=String(e)),e}function a(e){var t={next:function(){var t=e.shift();return{done:void 0===t,value:t}}};return w.iterable&&(t[Symbol.iterator]=function(){return t}),t}function s(e){this.map={},e instanceof s?e.forEach(function(e,t){this.append(t,e)},this):Array.isArray(e)?e.forEach(function(e){this.append(e[0],e[1])},this):e&&Object.getOwnPropertyNames(e).forEach(function(t){this.append(t,e[t])},this)}function c(e){if(e.bodyUsed)return Promise.reject(new TypeError("Already read"));e.bodyUsed=!0}function u(e){return new Promise(function(t,n){e.onload=function(){t(e.result)},e.onerror=function(){n(e.error)}})}function f(e){var t=new FileReader,n=u(t);return t.readAsArrayBuffer(e),n}function l(e){var t=new FileReader,n=u(t);return t.readAsText(e),n}function p(e){for(var t=new Uint8Array(e),n=new Array(t.length),r=0;r<t.length;r++)n[r]=String.fromCharCode(t[r]);return n.join("")}function d(e){if(e.slice)return e.slice(0);var t=new Uint8Array(e.byteLength);return t.set(new Uint8Array(e)),t.buffer}function v(){return this.bodyUsed=!1,this._initBody=function(e){this._bodyInit=e,e?"string"==typeof e?this._bodyText=e:w.blob&&Blob.prototype.isPrototypeOf(e)?this._bodyBlob=e:w.formData&&FormData.prototype.isPrototypeOf(e)?this._bodyFormData=e:w.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)?this._bodyText=e.toString():w.arrayBuffer&&w.blob&&r(e)?(this._bodyArrayBuffer=d(e.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer])):w.arrayBuffer&&(ArrayBuffer.prototype.isPrototypeOf(e)||$(e))?this._bodyArrayBuffer=d(e):this._bodyText=e=Object.prototype.toString.call(e):this._bodyText="",this.headers.get("content-type")||("string"==typeof e?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type?this.headers.set("content-type",this._bodyBlob.type):w.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)&&this.headers.set("content-type","application/x-www-form-urlencoded;charset=UTF-8"))},w.blob&&(this.blob=function(){var e=c(this);if(e)return e;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){return this._bodyArrayBuffer?c(this)||Promise.resolve(this._bodyArrayBuffer):this.blob().then(f)}),this.text=function(){var e=c(this);if(e)return e;if(this._bodyBlob)return l(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(p(this._bodyArrayBuffer));if(this._bodyFormData)throw new Error("could not read FormData body as text");return Promise.resolve(this._bodyText)},w.formData&&(this.formData=function(){return this.text().then(y)}),this.json=function(){return this.text().then(JSON.parse)},this}function h(e){var t=e.toUpperCase();return A.indexOf(t)>-1?t:e}function m(e,t){t=t||{};var n=t.body;if(e instanceof m){if(e.bodyUsed)throw new TypeError("Already read");this.url=e.url,this.credentials=e.credentials,t.headers||(this.headers=new s(e.headers)),this.method=e.method,this.mode=e.mode,this.signal=e.signal,n||null==e._bodyInit||(n=e._bodyInit,e.bodyUsed=!0)}else this.url=String(e);if(this.credentials=t.credentials||this.credentials||"same-origin",!t.headers&&this.headers||(this.headers=new s(t.headers)),this.method=h(t.method||this.method||"GET"),this.mode=t.mode||this.mode||null,this.signal=t.signal||this.signal,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&n)throw new TypeError("Body not allowed for GET or HEAD requests");this._initBody(n)}function y(e){var t=new FormData;return e.trim().split("&").forEach(function(e){if(e){var n=e.split("="),r=n.shift().replace(/\+/g," "),o=n.join("=").replace(/\+/g," ");t.append(decodeURIComponent(r),decodeURIComponent(o))}}),t}function g(e){var t=new s;return e.replace(/\r?\n[\t ]+/g," ").split(/\r?\n/).forEach(function(e){var n=e.split(":"),r=n.shift().trim();if(r){var o=n.join(":").trim();t.append(r,o)}}),t}function b(e,t){t||(t={}),this.type="default",this.status=void 0===t.status?200:t.status,this.ok=this.status>=200&&this.status<300,this.statusText="statusText"in t?t.statusText:"OK",this.headers=new s(t.headers),this.url=t.url||"",this._initBody(e)}function _(e,t){return new Promise(function(n,r){function o(){a.abort()}var i=new m(e,t);if(i.signal&&i.signal.aborted)return r(new k("Aborted","AbortError"));var a=new XMLHttpRequest;a.onload=function(){var e={status:a.status,statusText:a.statusText,headers:g(a.getAllResponseHeaders()||"")};e.url="responseURL"in a?a.responseURL:e.headers.get("X-Request-URL");var t="response"in a?a.response:a.responseText;n(new b(t,e))},a.onerror=function(){r(new TypeError("Network request failed"))},a.ontimeout=function(){r(new TypeError("Network request failed"))},a.onabort=function(){r(new k("Aborted","AbortError"))},a.open(i.method,i.url,!0),"include"===i.credentials?a.withCredentials=!0:"omit"===i.credentials&&(a.withCredentials=!1),"responseType"in a&&w.blob&&(a.responseType="blob"),i.headers.forEach(function(e,t){a.setRequestHeader(t,e)}),i.signal&&(i.signal.addEventListener("abort",o),a.onreadystatechange=function(){4===a.readyState&&i.signal.removeEventListener("abort",o)}),a.send(void 0===i._bodyInit?null:i._bodyInit)})}var w={searchParams:"URLSearchParams"in self,iterable:"Symbol"in self&&"iterator"in Symbol,blob:"FileReader"in self&&"Blob"in self&&function(){try{return new Blob,!0}catch(e){return!1}}(),formData:"FormData"in self,arrayBuffer:"ArrayBuffer"in self};if(w.arrayBuffer)var x=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],$=ArrayBuffer.isView||function(e){return e&&x.indexOf(Object.prototype.toString.call(e))>-1};s.prototype.append=function(e,t){e=o(e),t=i(t);var n=this.map[e];this.map[e]=n?n+", "+t:t},s.prototype.delete=function(e){delete this.map[o(e)]},s.prototype.get=function(e){return e=o(e),this.has(e)?this.map[e]:null},s.prototype.has=function(e){return this.map.hasOwnProperty(o(e))},s.prototype.set=function(e,t){this.map[o(e)]=i(t)},s.prototype.forEach=function(e,t){for(var n in this.map)this.map.hasOwnProperty(n)&&e.call(t,this.map[n],n,this)},s.prototype.keys=function(){var e=[];return this.forEach(function(t,n){e.push(n)}),a(e)},s.prototype.values=function(){var e=[];return this.forEach(function(t){e.push(t)}),a(e)},s.prototype.entries=function(){var e=[];return this.forEach(function(t,n){e.push([n,t])}),a(e)},w.iterable&&(s.prototype[Symbol.iterator]=s.prototype.entries);var A=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];m.prototype.clone=function(){return new m(this,{body:this._bodyInit})},v.call(m.prototype),v.call(b.prototype),b.prototype.clone=function(){return new b(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new s(this.headers),url:this.url})},b.error=function(){var e=new b(null,{status:0,statusText:""});return e.type="error",e};var C=[301,302,303,307,308];b.redirect=function(e,t){if(-1===C.indexOf(t))throw new RangeError("Invalid status code");return new b(null,{status:t,headers:{location:e}})};var k=self.DOMException;try{new k}catch(e){k=function(e,t){this.message=e,this.name=t;var n=Error(e);this.stack=n.stack},k.prototype=Object.create(Error.prototype),k.prototype.constructor=k}_.polyfill=!0,self.fetch||(self.fetch=_,self.Headers=s,self.Request=m,self.Response=b)},,,function(e,t,n){e.exports=n(19)},function(e,t,n){"use strict";function r(e){var t=new a(e),n=i(a.prototype.request,t);return o.extend(n,a.prototype,t),o.extend(n,t),n}var o=n(0),i=n(6),a=n(21),s=n(3),c=r(s);c.Axios=a,c.create=function(e){return r(o.merge(s,e))},c.Cancel=n(10),c.CancelToken=n(35),c.isCancel=n(9),c.all=function(e){return Promise.all(e)},c.spread=n(36),e.exports=c,e.exports.default=c},function(e,t){function n(e){return!!e.constructor&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)}function r(e){return"function"==typeof e.readFloatLE&&"function"==typeof e.slice&&n(e.slice(0,0))}/*!
|
7 |
+
* Determine if an object is a Buffer
|
8 |
+
*
|
9 |
+
* @author Feross Aboukhadijeh <https://feross.org>
|
10 |
+
* @license MIT
|
11 |
+
*/
|
12 |
+
e.exports=function(e){return null!=e&&(n(e)||r(e)||!!e._isBuffer)}},function(e,t,n){"use strict";function r(e){this.defaults=e,this.interceptors={request:new a,response:new a}}var o=n(3),i=n(0),a=n(30),s=n(31);r.prototype.request=function(e){"string"==typeof e&&(e=i.merge({url:arguments[0]},arguments[1])),e=i.merge(o,{method:"get"},this.defaults,e),e.method=e.method.toLowerCase();var t=[s,void 0],n=Promise.resolve(e);for(this.interceptors.request.forEach(function(e){t.unshift(e.fulfilled,e.rejected)}),this.interceptors.response.forEach(function(e){t.push(e.fulfilled,e.rejected)});t.length;)n=n.then(t.shift(),t.shift());return n},i.forEach(["delete","get","head","options"],function(e){r.prototype[e]=function(t,n){return this.request(i.merge(n||{},{method:e,url:t}))}}),i.forEach(["post","put","patch"],function(e){r.prototype[e]=function(t,n,r){return this.request(i.merge(r||{},{method:e,url:t,data:n}))}}),e.exports=r},function(e,t,n){"use strict";var r=n(0);e.exports=function(e,t){r.forEach(e,function(n,r){r!==t&&r.toUpperCase()===t.toUpperCase()&&(e[t]=n,delete e[r])})}},function(e,t,n){"use strict";var r=n(8);e.exports=function(e,t,n){var o=n.config.validateStatus;n.status&&o&&!o(n.status)?t(r("Request failed with status code "+n.status,n.config,null,n.request,n)):e(n)}},function(e,t,n){"use strict";e.exports=function(e,t,n,r,o){return e.config=t,n&&(e.code=n),e.request=r,e.response=o,e}},function(e,t,n){"use strict";function r(e){return encodeURIComponent(e).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}var o=n(0);e.exports=function(e,t,n){if(!t)return e;var i;if(n)i=n(t);else if(o.isURLSearchParams(t))i=t.toString();else{var a=[];o.forEach(t,function(e,t){null!==e&&void 0!==e&&(o.isArray(e)?t+="[]":e=[e],o.forEach(e,function(e){o.isDate(e)?e=e.toISOString():o.isObject(e)&&(e=JSON.stringify(e)),a.push(r(t)+"="+r(e))}))}),i=a.join("&")}return i&&(e+=(-1===e.indexOf("?")?"?":"&")+i),e}},function(e,t,n){"use strict";var r=n(0),o=["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"];e.exports=function(e){var t,n,i,a={};return e?(r.forEach(e.split("\n"),function(e){if(i=e.indexOf(":"),t=r.trim(e.substr(0,i)).toLowerCase(),n=r.trim(e.substr(i+1)),t){if(a[t]&&o.indexOf(t)>=0)return;a[t]="set-cookie"===t?(a[t]?a[t]:[]).concat([n]):a[t]?a[t]+", "+n:n}}),a):a}},function(e,t,n){"use strict";var r=n(0);e.exports=r.isStandardBrowserEnv()?function(){function e(e){var t=e;return n&&(o.setAttribute("href",t),t=o.href),o.setAttribute("href",t),{href:o.href,protocol:o.protocol?o.protocol.replace(/:$/,""):"",host:o.host,search:o.search?o.search.replace(/^\?/,""):"",hash:o.hash?o.hash.replace(/^#/,""):"",hostname:o.hostname,port:o.port,pathname:"/"===o.pathname.charAt(0)?o.pathname:"/"+o.pathname}}var t,n=/(msie|trident)/i.test(navigator.userAgent),o=document.createElement("a");return t=e(window.location.href),function(n){var o=r.isString(n)?e(n):n;return o.protocol===t.protocol&&o.host===t.host}}():function(){return function(){return!0}}()},function(e,t,n){"use strict";function r(){this.message="String contains an invalid character"}function o(e){for(var t,n,o=String(e),a="",s=0,c=i;o.charAt(0|s)||(c="=",s%1);a+=c.charAt(63&t>>8-s%1*8)){if((n=o.charCodeAt(s+=.75))>255)throw new r;t=t<<8|n}return a}var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";r.prototype=new Error,r.prototype.code=5,r.prototype.name="InvalidCharacterError",e.exports=o},function(e,t,n){"use strict";var r=n(0);e.exports=r.isStandardBrowserEnv()?function(){return{write:function(e,t,n,o,i,a){var s=[];s.push(e+"="+encodeURIComponent(t)),r.isNumber(n)&&s.push("expires="+new Date(n).toGMTString()),r.isString(o)&&s.push("path="+o),r.isString(i)&&s.push("domain="+i),!0===a&&s.push("secure"),document.cookie=s.join("; ")},read:function(e){var t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove:function(e){this.write(e,"",Date.now()-864e5)}}}():function(){return{write:function(){},read:function(){return null},remove:function(){}}}()},function(e,t,n){"use strict";function r(){this.handlers=[]}var o=n(0);r.prototype.use=function(e,t){return this.handlers.push({fulfilled:e,rejected:t}),this.handlers.length-1},r.prototype.eject=function(e){this.handlers[e]&&(this.handlers[e]=null)},r.prototype.forEach=function(e){o.forEach(this.handlers,function(t){null!==t&&e(t)})},e.exports=r},function(e,t,n){"use strict";function r(e){e.cancelToken&&e.cancelToken.throwIfRequested()}var o=n(0),i=n(32),a=n(9),s=n(3),c=n(33),u=n(34);e.exports=function(e){return r(e),e.baseURL&&!c(e.url)&&(e.url=u(e.baseURL,e.url)),e.headers=e.headers||{},e.data=i(e.data,e.headers,e.transformRequest),e.headers=o.merge(e.headers.common||{},e.headers[e.method]||{},e.headers||{}),o.forEach(["delete","get","head","post","put","patch","common"],function(t){delete e.headers[t]}),(e.adapter||s.adapter)(e).then(function(t){return r(e),t.data=i(t.data,t.headers,e.transformResponse),t},function(t){return a(t)||(r(e),t&&t.response&&(t.response.data=i(t.response.data,t.response.headers,e.transformResponse))),Promise.reject(t)})}},function(e,t,n){"use strict";var r=n(0);e.exports=function(e,t,n){return r.forEach(n,function(n){e=n(e,t)}),e}},function(e,t,n){"use strict";e.exports=function(e){return/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(e)}},function(e,t,n){"use strict";e.exports=function(e,t){return t?e.replace(/\/+$/,"")+"/"+t.replace(/^\/+/,""):e}},function(e,t,n){"use strict";function r(e){if("function"!=typeof e)throw new TypeError("executor must be a function.");var t;this.promise=new Promise(function(e){t=e});var n=this;e(function(e){n.reason||(n.reason=new o(e),t(n.reason))})}var o=n(10);r.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},r.source=function(){var e;return{token:new r(function(t){e=t}),cancel:e}},e.exports=r},function(e,t,n){"use strict";e.exports=function(e){return function(t){return e.apply(null,t)}}}]);
|
readme.txt
CHANGED
@@ -3,113 +3,118 @@ Contributors: RebelCode, jeangalea, markzahra, Mekku, xedin.unknown,
|
|
3 |
Plugin URI: https://www.wprssaggregator.com
|
4 |
Tags: RSS import, RSS aggregator, autoblog, content curation, feed to post
|
5 |
Requires at least: 4.0 or higher
|
6 |
-
Tested up to: 5.
|
7 |
Requires PHP: 5.3.9 or higher
|
8 |
-
Stable tag: 4.12
|
9 |
License: GPLv3
|
10 |
|
11 |
WP RSS Aggregator is the original & most popular WordPress solution for importing RSS feeds, auto-blogging, content curation & aggregation.
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
-
WP RSS Aggregator is the original and best plugin for easily importing, merging and displaying RSS and Atom feeds on your WordPress site. It's the most comprehensive and elegant RSS feed
|
16 |
|
17 |
-
==
|
18 |
-
|
19 |
-
Content remains an integral part of any website, which is why we provide a reliable solution to share content from any source on your own WordPress site. Whether sharing your own content across sites or importing news, tutorials, Youtube videos & more, from top sources around the world, this is the only solution you need.
|
20 |
|
21 |
* No limit on the number of sources you can import from.
|
22 |
* No limit on the number of items you can import.
|
23 |
* Automate each import on its own schedule.
|
24 |
-
* Use our [shortcode](https://kb.wprssaggregator.com/article/54-how-to-use-the-shortcode-to-display-feed-items) to easily display items.
|
25 |
-
|
26 |
-
[youtube https://www.youtube.com/watch?v=OgB3veegtz4]
|
27 |
-
|
28 |
-
== More Free Features ==
|
29 |
-
|
30 |
-
* Feed auto-discovery to add sources without the exact feed URL
|
31 |
* Open YouTube, DailyMotion and Vimeo videos directly
|
32 |
-
* Only import feed items with [unique titles](https://kb.wprssaggregator.com/article/52-general-settings) to prevent duplicates
|
33 |
* Limit the number of feed items stored to maintain performance
|
34 |
-
*
|
35 |
-
*
|
36 |
-
*
|
37 |
-
* Style the shortcode display with [some basic CSS](https://kb.wprssaggregator.com/article/196-shortcode-styles-classes)
|
38 |
-
* Create a [custom RSS feed](https://kb.wprssaggregator.com/article/219-how-to-create-custom-rss-feeds) from imported feed items to use elsewhere
|
39 |
-
* Extendable via [action and filter hooks](https://kb.wprssaggregator.com/collection/72-for-developers)
|
40 |
-
* Integrated with the Simplepie library that comes with WordPress.
|
41 |
-
* Multilingual ready
|
42 |
|
43 |
[Click here to learn more about this free core plugin.](https://www.wprssaggregator.com/extension/core-plugin/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_learn_more&utm_content=learn_more)
|
44 |
|
45 |
-
==
|
46 |
|
47 |
-
Increase your WordPress site's credibility and popularity
|
48 |
|
49 |
-
|
|
|
50 |
|
51 |
-
|
52 |
|
53 |
-
|
54 |
-
* Import into Posts or any Custom Post Type on your site
|
55 |
-
* Automatically categorise imported posts and assign tags
|
56 |
-
* Import media within the content and set featured images
|
57 |
-
* Import the original author's details or assign a new one
|
58 |
-
* Add you own custom content before or after the imported posts
|
59 |
-
* Custom field mapping for the more experienced among you
|
60 |
-
* Extract unwanted elements from the original source
|
61 |
-
* Import only what you need with keyword, phrase and tag filters
|
62 |
-
* Connect to our premium full text service to automatically import the full content from sources that only provide excerpts or are missing images and/or videos
|
63 |
|
64 |
-
|
|
|
|
|
65 |
|
66 |
-
*
|
67 |
-
* **[Full Text RSS Feeds](https://www.wprssaggregator.com/extension/full-text-rss-feeds/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_ftr_link&utm_content=ftr_link)**
|
68 |
-
* **[Keyword Filtering](https://www.wprssaggregator.com/extension/keyword-filtering/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_kf_link&utm_content=kf_link)**
|
69 |
|
70 |
-
|
71 |
|
72 |
-
|
73 |
|
74 |
-
*
|
75 |
-
*
|
|
|
|
|
|
|
|
|
|
|
76 |
|
77 |
-
|
78 |
|
79 |
-
|
80 |
-
* [Crypto Headlines](http://cryptoheadlines.com/)
|
81 |
-
* [Travel Blogger Community](http://travelbloggercommunity.com/)
|
82 |
|
83 |
-
|
84 |
|
85 |
-
|
86 |
|
87 |
-
|
88 |
|
89 |
-
[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
|
91 |
-
|
92 |
|
93 |
-
|
94 |
|
95 |
* **[Excerpts & Thumbnails](https://www.wprssaggregator.com/extension/excerpts-thumbnails/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_et_link&utm_content=et_link)**
|
96 |
* **[Categories](https://www.wprssaggregator.com/extension/categories/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_cat_link&utm_content=cat_link)**
|
|
|
|
|
|
|
97 |
|
98 |
-
|
99 |
|
100 |
-
|
|
|
|
|
101 |
|
102 |
== We Stand Behind What We Build ==
|
103 |
|
104 |
Our comprehensive [Knowledge Base](https://kb.wprssaggregator.com/) provides you with everything you need to install, set up and customise the plugin to your needs. You can also browse through a number of FAQs to get started.
|
105 |
|
106 |
-
If that doesn't do the trick, we provide support for the free version of WP RSS Aggregator via the
|
107 |
|
108 |
== Related Info ==
|
109 |
|
110 |
-
WP RSS Aggregator and its premium add-ons are compatible with the new Gutenberg block editor introduced in the revolutionary WordPress 5.0. You can find more information about how the two work together [here](https://kb.wprssaggregator.com/article/444-gutenberg-compatibility-core-plugin).
|
111 |
|
112 |
-
We provide a [Feed Creator](http://createfeed.wprssaggregator.com/) service that allows you to generate RSS feeds from any webpage, even if it doesn't have its own RSS feed.
|
113 |
|
114 |
Our terms & conditions can be found [here](https://www.wprssaggregator.com/terms-conditions/).
|
115 |
|
@@ -243,15 +248,15 @@ Our complete Knowledge Base with FAQs included can be found [here](https://kb.wp
|
|
243 |
|
244 |
== Screenshots ==
|
245 |
|
246 |
-
1. The
|
247 |
|
248 |
-
2. A customised shortcode display using some simple [CSS](https://kb.wprssaggregator.com/article/196-shortcode-styles-classes)
|
249 |
|
250 |
-
3. Another customised display of the Feed Items using CSS styling, but with the [Excerpts & Thumbnails](http://www.wprssaggregator.com/extensions/excerpts-thumbnails) add-on
|
251 |
|
252 |
-
4. Posts imported using Feed to Post
|
253 |
|
254 |
-
5. Youtube videos imported using Feed to Post
|
255 |
|
256 |
6. Adding/Editing a feed source
|
257 |
|
@@ -263,6 +268,15 @@ Our complete Knowledge Base with FAQs included can be found [here](https://kb.wp
|
|
263 |
|
264 |
== Changelog ==
|
265 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
266 |
= 4.12 (2019-01-29) =
|
267 |
* The plugin now checks if its running on PHP 5.3.9, and deactivates itself when not.
|
268 |
* Added message informing users that v4.13 will drop support for PHP 5.3.
|
3 |
Plugin URI: https://www.wprssaggregator.com
|
4 |
Tags: RSS import, RSS aggregator, autoblog, content curation, feed to post
|
5 |
Requires at least: 4.0 or higher
|
6 |
+
Tested up to: 5.1
|
7 |
Requires PHP: 5.3.9 or higher
|
8 |
+
Stable tag: 4.12.1
|
9 |
License: GPLv3
|
10 |
|
11 |
WP RSS Aggregator is the original & most popular WordPress solution for importing RSS feeds, auto-blogging, content curation & aggregation.
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
+
WP RSS Aggregator is the original and best plugin for easily importing, merging and displaying RSS and Atom feeds on your WordPress site. It's the most comprehensive and elegant RSS feed importer for WordPress.
|
16 |
|
17 |
+
== Automatically Import RSS Feeds & Display Them On Your Site ==
|
|
|
|
|
18 |
|
19 |
* No limit on the number of sources you can import from.
|
20 |
* No limit on the number of items you can import.
|
21 |
* Automate each import on its own schedule.
|
22 |
+
* Use our [wp-rss-aggregator] [shortcode](https://kb.wprssaggregator.com/article/54-how-to-use-the-shortcode-to-display-feed-items) to easily display items.
|
23 |
+
* Feed auto-discovery to add sources without the exact RSS feed URL
|
|
|
|
|
|
|
|
|
|
|
24 |
* Open YouTube, DailyMotion and Vimeo videos directly
|
|
|
25 |
* Limit the number of feed items stored to maintain performance
|
26 |
+
* Choose to show, hide and/or link the author, source and publish date.
|
27 |
+
* Create a custom RSS feed from imported feed items to use elsewhere
|
28 |
+
* Extendable via action and filter hooks
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
[Click here to learn more about this free core plugin.](https://www.wprssaggregator.com/extension/core-plugin/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_learn_more&utm_content=learn_more)
|
31 |
|
32 |
+
== Bloggers & Content Marketers ==
|
33 |
|
34 |
+
Increase your WordPress site's credibility and popularity by importing full or partial Posts into your site with our premium add-ons.
|
35 |
|
36 |
+
* Beginner Bloggers and Copywriters - Find and display fresh, new content to **engage and grow your audience**.
|
37 |
+
* Site Owners & Content Marketers - Curate content to **keep your avid readers on your site for longer**.
|
38 |
|
39 |
+
== SEO Benefits from RSS Feeds ==
|
40 |
|
41 |
+
Importing RSS feeds alone won't improve your site's SEO, however, if you curate content (articles, tutorials, videos, listings, etc) and bring in quality traffic, the benefits begin to appear:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
|
43 |
+
* Generate lots of new backlinks to your site.
|
44 |
+
* Enhance your online presence and gain more trust.
|
45 |
+
* And therefore, you can help boost your SEO!
|
46 |
|
47 |
+
*Quick sidetone: Don't steal other people's work; give credit where it's due.*
|
|
|
|
|
48 |
|
49 |
+
== Who is this useful for? ==
|
50 |
|
51 |
+
Importing and displaying RSS feeds is helpful for many types of sites:
|
52 |
|
53 |
+
* Curate news, videos and more from the top sources in your niche.
|
54 |
+
* Add related posts from other sites to your site.
|
55 |
+
* Curate job, real estate or other listings for your market or niche.
|
56 |
+
* Show Youtube videos on your site to engage more visitors.
|
57 |
+
* Aggregate podcast episodes related to your hobby or profession.
|
58 |
+
* Writers, list your articles from across the web on your main site.
|
59 |
+
* And much more.
|
60 |
|
61 |
+
For example, [WP News Desk](http://wpnewsdesk.com/) curates WordPress news, tutorials and more from over 100 trusted sources. [Travel Blogger Community](http://travelbloggercommunity.com/) does something similar to share blog posts from well-known travellers. [Crypto Headlines](https://cryptoheadlines.com/youtube-videos/) shares Youtube videos from popular Youtubers. **What will you do with WP RSS Aggregator?**
|
62 |
|
63 |
+
== Premium Add-ons to Import Posts ==
|
|
|
|
|
64 |
|
65 |
+
Import RSS feeds as WordPress posts or any other custom post type to display them just the way you want on your site.
|
66 |
|
67 |
+
**[Advanced Feeds Bundle](https://www.wprssaggregator.com/extension/advanced-feeds-bundle/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_afb_link&utm_content=afb_link)** | [Free Demo](http://demo.wprssaggregator.com/)
|
68 |
|
69 |
+
This bundle is made up of 3 great add-ons:
|
70 |
|
71 |
+
* **[Feed to Post](https://www.wprssaggregator.com/extension/feed-to-post/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_f2p_link&utm_content=f2p_link)**
|
72 |
+
* **[Full Text RSS Feeds](https://www.wprssaggregator.com/extension/full-text-rss-feeds/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_ftr_link&utm_content=ftr_link)**
|
73 |
+
* **[Keyword Filtering](https://www.wprssaggregator.com/extension/keyword-filtering/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_kf_link&utm_content=kf_link)**
|
74 |
+
|
75 |
+
[youtube https://www.youtube.com/watch?v=-2z_bNws2MM]
|
76 |
+
|
77 |
+
Here's a quick look at what these add-ons can offer:
|
78 |
+
|
79 |
+
* Import Posts as Drafts or set them to Publish upon import.
|
80 |
+
* Automatically categorise imported posts and/or assign tags.
|
81 |
+
* Import all media within the content and pre-set featured images.
|
82 |
+
* Import the original author's details or assign an existing user.
|
83 |
+
* Automatically add you own custom content before or after imported posts.
|
84 |
+
* Custom field mapping for the more experienced among you.
|
85 |
+
* Exclude unwanted elements from the original source with extraction rules.
|
86 |
+
* Import only the Posts you want with keyword, phrase and tag filters.
|
87 |
+
* Connect to our premium full text service to import the full content from sources that are missing text, images and more in the original RSS feeds.
|
88 |
+
|
89 |
+
== Premium Add-ons to Enhance the Shortcode Display ==
|
90 |
|
91 |
+
**[Simple Feeds Bundle](https://www.wprssaggregator.com/extension/simple-feeds-bundle/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_afb_link&utm_content=afb_link)** | [Free Demo](http://simple.wprssaggregator.com/)
|
92 |
|
93 |
+
This bundle is made up of 3 add-ons:
|
94 |
|
95 |
* **[Excerpts & Thumbnails](https://www.wprssaggregator.com/extension/excerpts-thumbnails/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_et_link&utm_content=et_link)**
|
96 |
* **[Categories](https://www.wprssaggregator.com/extension/categories/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_cat_link&utm_content=cat_link)**
|
97 |
+
* **[Keyword Filtering](https://www.wprssaggregator.com/extension/keyword-filtering/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_kf_link&utm_content=kf_link)**
|
98 |
+
|
99 |
+
[youtube https://www.youtube.com/watch?v=Wx2gkEq3MxU]
|
100 |
|
101 |
+
== Showcase Of WordPress Sites Running WP RSS Aggregator ==
|
102 |
|
103 |
+
Browse through our entire [**Showcase**](https://www.wprssaggregator.com/showcase/) to see how WP RSS Aggregator is being put to great use on a large variety of websites.
|
104 |
+
|
105 |
+
You can even take things a step further by using our 3rd-party content spinner integrations or by creating a mobile app using the imported content. [Check out this tutorial from MobiLoud](https://www.mobiloud.com/help/knowledge-base/wp-rss-aggregator-mobile-app/) on how we built an app for the WP News Desk website.
|
106 |
|
107 |
== We Stand Behind What We Build ==
|
108 |
|
109 |
Our comprehensive [Knowledge Base](https://kb.wprssaggregator.com/) provides you with everything you need to install, set up and customise the plugin to your needs. You can also browse through a number of FAQs to get started.
|
110 |
|
111 |
+
If that doesn't do the trick, we provide support for the free version of WP RSS Aggregator via the support forum [here](https://wordpress.org/support/plugin/wp-rss-aggregator), while for premium support (owners of valid premium add-on licenses) and pre-sales questions please contact us via our [premium support channel](https://www.wprssaggregator.com/contact/?utm_source=wordpress-dot-org&utm_medium=readme&utm_campaign=readme_contact_link&utm_content=contact_link).
|
112 |
|
113 |
== Related Info ==
|
114 |
|
115 |
+
WP RSS Aggregator and its premium add-ons are compatible with the new Gutenberg block editor introduced in the revolutionary WordPress 5.0. You can find more information about how the two work together [here](https://kb.wprssaggregator.com/article/444-gutenberg-compatibility-core-plugin). A dedicated Gutenberg block is in development.
|
116 |
|
117 |
+
We provide a [Feed Creator](http://createfeed.wprssaggregator.com/) service that allows you to generate RSS feeds from any webpage, even if it doesn't have its own RSS feed. It provides inline documentation on how to use the service.
|
118 |
|
119 |
Our terms & conditions can be found [here](https://www.wprssaggregator.com/terms-conditions/).
|
120 |
|
248 |
|
249 |
== Screenshots ==
|
250 |
|
251 |
+
1. The free shortcode display of Feed items imported by WP RSS Aggregator
|
252 |
|
253 |
+
2. A customised shortcode display using some simple [CSS changes](https://kb.wprssaggregator.com/article/196-shortcode-styles-classes)
|
254 |
|
255 |
+
3. Another customised display of the Feed Items using CSS styling, but with the [Excerpts & Thumbnails](http://www.wprssaggregator.com/extensions/excerpts-thumbnails) add-on
|
256 |
|
257 |
+
4. Posts imported using the Feed to Post add-on
|
258 |
|
259 |
+
5. Youtube videos imported using the Feed to Post add-on
|
260 |
|
261 |
6. Adding/Editing a feed source
|
262 |
|
268 |
|
269 |
== Changelog ==
|
270 |
|
271 |
+
= 4.12.1 (2019-02-27) =
|
272 |
+
* Added a modal with an optional poll when the plugin is deactivated.
|
273 |
+
* Improved the core plugin's on-boarding process for brand new users.
|
274 |
+
* Fixed the "Sorted" error appearing constantly in the debug log.
|
275 |
+
* The timeout for the truncating posts hook has been extended.
|
276 |
+
* Fixed PHP warnings appearing on WordPress multisite.
|
277 |
+
* Fixed PHP notice appearing on Feed Items page.
|
278 |
+
* Fixed strict standards notice appearing on settings import.
|
279 |
+
|
280 |
= 4.12 (2019-01-29) =
|
281 |
* The plugin now checks if its running on PHP 5.3.9, and deactivates itself when not.
|
282 |
* Added message informing users that v4.13 will drop support for PHP 5.3.
|
templates/admin-update-page.twig
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="wrap wrap--wpra-update">
|
2 |
+
<div class="wpra-update wpra-text-center">
|
3 |
+
<div class="wpra-update__logo">
|
4 |
+
<img src="https://www.wprssaggregator.com/wp-content/themes/wp_rss_theme/assets/images/wp_rss_logo.png">
|
5 |
+
</div>
|
6 |
+
<div class="wpra-update-head__copy">
|
7 |
+
<div class="wpra-update-head__title">{{ title }}</div>
|
8 |
+
<div class="wpra-update-head__link">
|
9 |
+
<a href="{{ url.main }}">Skip the update details and get back to the plugin.</a>
|
10 |
+
</div>
|
11 |
+
</div>
|
12 |
+
</div>
|
13 |
+
|
14 |
+
<hr class="wp-header-end">
|
15 |
+
|
16 |
+
<div id="wpra-update-app">
|
17 |
+
<div class="postbox">
|
18 |
+
<div class="inside wpra-update-feature">
|
19 |
+
<div class="wpra-update-feature__text">
|
20 |
+
<h3>Better self-help solutions right on your site</h3>
|
21 |
+
<p>You can now make the best use of our knowledge base and support options from right within your
|
22 |
+
WordPress Dashboard! Through our support beacon you will have access to our complete knowledge base
|
23 |
+
without ever leaving your site. It even includes a contact form should you need to ask us any
|
24 |
+
questions.</p>
|
25 |
+
<p>The beacon will be visible on the bottom right-hand corner of only WP RSS Aggregator's pages. It can
|
26 |
+
be enabled or disabled at any time through the Help & Support page in our sub-menu on the left.</p>
|
27 |
+
<form method="post" class="wpra-inline-form">
|
28 |
+
{% if beacon_enabled == false %}
|
29 |
+
<button class="button button-primary button-large" type="submit" name="wprss_hs_beacon_enabled"
|
30 |
+
value="1">Enable Support Beacon
|
31 |
+
</button>
|
32 |
+
{% else %}
|
33 |
+
<button class="button button-large" type="submit" name="wprss_hs_beacon_enabled" value="0">
|
34 |
+
Disable Support Beacon
|
35 |
+
</button>
|
36 |
+
{% endif %}
|
37 |
+
{{ beacon_nonce_field | raw }}
|
38 |
+
</form>
|
39 |
+
</div>
|
40 |
+
<div class="wpra-update-feature__image">
|
41 |
+
<img src="{{ path.images }}/wp-rss-aggregator-support-beacon.png" alt="Support Beacon">
|
42 |
+
</div>
|
43 |
+
</div>
|
44 |
+
</div>
|
45 |
+
|
46 |
+
<div class="postbox">
|
47 |
+
<div class="inside">
|
48 |
+
<h3>Other fixes and improvements</h3>
|
49 |
+
<ul class="wpra-updates">
|
50 |
+
<li>Performance improvements across the core plugin.</li>
|
51 |
+
<li>Sorted out the "Sorted" error appearing constantly in the debug log.</li>
|
52 |
+
<li>Improved the core plugin's on-boarding process for brand new users.</li>
|
53 |
+
<li>The timeout for the truncating posts hook has been extended.</li>
|
54 |
+
<li>Fixed PHP warnings appearing on WordPress multisite.</li>
|
55 |
+
<li>Fixed PHP notice appearing on Feed Items page.</li>
|
56 |
+
<li>Fixed strict standards notice appearing on settings import.</li>
|
57 |
+
</ul>
|
58 |
+
</div>
|
59 |
+
</div>
|
60 |
+
|
61 |
+
<div class="wpra-text-center">
|
62 |
+
<a class="button button-large button-icon" href="{{ url.main }}">
|
63 |
+
Continue to WP RSS Aggregator
|
64 |
+
<span class="dashicons dashicons-arrow-right-alt2"></span>
|
65 |
+
</a>
|
66 |
+
</div>
|
67 |
+
|
68 |
+
<div class="wpra-text-center wpra-links">
|
69 |
+
<a href="{{ url.website }}" target="_blank">Visit website</a> |
|
70 |
+
<a href="{{ url.support }}" target="_blank">Contact support</a> |
|
71 |
+
<a href="{{ url.kb }}" target="_blank">Browse knowledge base</a>
|
72 |
+
</div>
|
73 |
+
</div>
|
74 |
+
|
75 |
+
<br class="clear">
|
76 |
+
</div>
|
vendor/autoload.php
CHANGED
@@ -4,4 +4,4 @@
|
|
4 |
|
5 |
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
|
7 |
-
return
|
4 |
|
5 |
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
|
7 |
+
return ComposerAutoloaderInitf863e81b820c8b6030ee7817e9830c58::getLoader();
|
vendor/composer/ClassLoader.php
CHANGED
@@ -279,7 +279,7 @@ class ClassLoader
|
|
279 |
*/
|
280 |
public function setApcuPrefix($apcuPrefix)
|
281 |
{
|
282 |
-
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
|
283 |
}
|
284 |
|
285 |
/**
|
@@ -377,7 +377,7 @@ class ClassLoader
|
|
377 |
$subPath = $class;
|
378 |
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
379 |
$subPath = substr($subPath, 0, $lastPos);
|
380 |
-
$search = $subPath.'\\';
|
381 |
if (isset($this->prefixDirsPsr4[$search])) {
|
382 |
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
383 |
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
279 |
*/
|
280 |
public function setApcuPrefix($apcuPrefix)
|
281 |
{
|
282 |
+
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
283 |
}
|
284 |
|
285 |
/**
|
377 |
$subPath = $class;
|
378 |
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
379 |
$subPath = substr($subPath, 0, $lastPos);
|
380 |
+
$search = $subPath . '\\';
|
381 |
if (isset($this->prefixDirsPsr4[$search])) {
|
382 |
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
383 |
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
vendor/composer/autoload_real.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
-
class
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
@@ -19,15 +19,15 @@ class ComposerAutoloaderInit0545fe6ed375a2225242ff880484f3bb
|
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
-
spl_autoload_register(array('
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
-
spl_autoload_unregister(array('
|
25 |
|
26 |
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
27 |
if ($useStaticLoader) {
|
28 |
require_once __DIR__ . '/autoload_static.php';
|
29 |
|
30 |
-
call_user_func(\Composer\Autoload\
|
31 |
} else {
|
32 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
foreach ($map as $namespace => $path) {
|
@@ -48,19 +48,19 @@ class ComposerAutoloaderInit0545fe6ed375a2225242ff880484f3bb
|
|
48 |
$loader->register(true);
|
49 |
|
50 |
if ($useStaticLoader) {
|
51 |
-
$includeFiles = Composer\Autoload\
|
52 |
} else {
|
53 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
54 |
}
|
55 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
56 |
-
|
57 |
}
|
58 |
|
59 |
return $loader;
|
60 |
}
|
61 |
}
|
62 |
|
63 |
-
function
|
64 |
{
|
65 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
66 |
require $file;
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInitf863e81b820c8b6030ee7817e9830c58
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInitf863e81b820c8b6030ee7817e9830c58', 'loadClassLoader'), true, true);
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInitf863e81b820c8b6030ee7817e9830c58', 'loadClassLoader'));
|
25 |
|
26 |
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
27 |
if ($useStaticLoader) {
|
28 |
require_once __DIR__ . '/autoload_static.php';
|
29 |
|
30 |
+
call_user_func(\Composer\Autoload\ComposerStaticInitf863e81b820c8b6030ee7817e9830c58::getInitializer($loader));
|
31 |
} else {
|
32 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
foreach ($map as $namespace => $path) {
|
48 |
$loader->register(true);
|
49 |
|
50 |
if ($useStaticLoader) {
|
51 |
+
$includeFiles = Composer\Autoload\ComposerStaticInitf863e81b820c8b6030ee7817e9830c58::$files;
|
52 |
} else {
|
53 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
54 |
}
|
55 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
56 |
+
composerRequiref863e81b820c8b6030ee7817e9830c58($fileIdentifier, $file);
|
57 |
}
|
58 |
|
59 |
return $loader;
|
60 |
}
|
61 |
}
|
62 |
|
63 |
+
function composerRequiref863e81b820c8b6030ee7817e9830c58($fileIdentifier, $file)
|
64 |
{
|
65 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
66 |
require $file;
|
vendor/composer/autoload_static.php
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
-
class
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
@@ -85,9 +85,9 @@ class ComposerStaticInit0545fe6ed375a2225242ff880484f3bb
|
|
85 |
public static function getInitializer(ClassLoader $loader)
|
86 |
{
|
87 |
return \Closure::bind(function () use ($loader) {
|
88 |
-
$loader->prefixLengthsPsr4 =
|
89 |
-
$loader->prefixDirsPsr4 =
|
90 |
-
$loader->prefixesPsr0 =
|
91 |
|
92 |
}, null, ClassLoader::class);
|
93 |
}
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
+
class ComposerStaticInitf863e81b820c8b6030ee7817e9830c58
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
85 |
public static function getInitializer(ClassLoader $loader)
|
86 |
{
|
87 |
return \Closure::bind(function () use ($loader) {
|
88 |
+
$loader->prefixLengthsPsr4 = ComposerStaticInitf863e81b820c8b6030ee7817e9830c58::$prefixLengthsPsr4;
|
89 |
+
$loader->prefixDirsPsr4 = ComposerStaticInitf863e81b820c8b6030ee7817e9830c58::$prefixDirsPsr4;
|
90 |
+
$loader->prefixesPsr0 = ComposerStaticInitf863e81b820c8b6030ee7817e9830c58::$prefixesPsr0;
|
91 |
|
92 |
}, null, ClassLoader::class);
|
93 |
}
|
vendor/composer/installed.json
CHANGED
@@ -484,17 +484,17 @@
|
|
484 |
},
|
485 |
{
|
486 |
"name": "symfony/polyfill-ctype",
|
487 |
-
"version": "
|
488 |
-
"version_normalized": "
|
489 |
"source": {
|
490 |
"type": "git",
|
491 |
"url": "https://github.com/symfony/polyfill-ctype.git",
|
492 |
-
"reference": "
|
493 |
},
|
494 |
"dist": {
|
495 |
"type": "zip",
|
496 |
-
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/
|
497 |
-
"reference": "
|
498 |
"shasum": ""
|
499 |
},
|
500 |
"require": {
|
@@ -503,14 +503,14 @@
|
|
503 |
"suggest": {
|
504 |
"ext-ctype": "For best performance"
|
505 |
},
|
506 |
-
"time": "
|
507 |
"type": "library",
|
508 |
"extra": {
|
509 |
"branch-alias": {
|
510 |
-
"dev-master": "1.
|
511 |
}
|
512 |
},
|
513 |
-
"installation-source": "
|
514 |
"autoload": {
|
515 |
"psr-4": {
|
516 |
"Symfony\\Polyfill\\Ctype\\": ""
|
@@ -549,12 +549,12 @@
|
|
549 |
"source": {
|
550 |
"type": "git",
|
551 |
"url": "https://github.com/twigphp/Twig.git",
|
552 |
-
"reference": "
|
553 |
},
|
554 |
"dist": {
|
555 |
"type": "zip",
|
556 |
-
"url": "https://api.github.com/repos/twigphp/Twig/zipball/
|
557 |
-
"reference": "
|
558 |
"shasum": ""
|
559 |
},
|
560 |
"require": {
|
@@ -566,11 +566,11 @@
|
|
566 |
"symfony/debug": "^2.7",
|
567 |
"symfony/phpunit-bridge": "^3.4.19|^4.1.8"
|
568 |
},
|
569 |
-
"time": "2019-
|
570 |
"type": "library",
|
571 |
"extra": {
|
572 |
"branch-alias": {
|
573 |
-
"dev-master": "1.
|
574 |
}
|
575 |
},
|
576 |
"installation-source": "source",
|
484 |
},
|
485 |
{
|
486 |
"name": "symfony/polyfill-ctype",
|
487 |
+
"version": "dev-master",
|
488 |
+
"version_normalized": "9999999-dev",
|
489 |
"source": {
|
490 |
"type": "git",
|
491 |
"url": "https://github.com/symfony/polyfill-ctype.git",
|
492 |
+
"reference": "82ebae02209c21113908c229e9883c419720738a"
|
493 |
},
|
494 |
"dist": {
|
495 |
"type": "zip",
|
496 |
+
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a",
|
497 |
+
"reference": "82ebae02209c21113908c229e9883c419720738a",
|
498 |
"shasum": ""
|
499 |
},
|
500 |
"require": {
|
503 |
"suggest": {
|
504 |
"ext-ctype": "For best performance"
|
505 |
},
|
506 |
+
"time": "2019-02-06T07:57:58+00:00",
|
507 |
"type": "library",
|
508 |
"extra": {
|
509 |
"branch-alias": {
|
510 |
+
"dev-master": "1.11-dev"
|
511 |
}
|
512 |
},
|
513 |
+
"installation-source": "source",
|
514 |
"autoload": {
|
515 |
"psr-4": {
|
516 |
"Symfony\\Polyfill\\Ctype\\": ""
|
549 |
"source": {
|
550 |
"type": "git",
|
551 |
"url": "https://github.com/twigphp/Twig.git",
|
552 |
+
"reference": "ea371bee8102f28e5d715d6410eb0d46fecf96b4"
|
553 |
},
|
554 |
"dist": {
|
555 |
"type": "zip",
|
556 |
+
"url": "https://api.github.com/repos/twigphp/Twig/zipball/ea371bee8102f28e5d715d6410eb0d46fecf96b4",
|
557 |
+
"reference": "ea371bee8102f28e5d715d6410eb0d46fecf96b4",
|
558 |
"shasum": ""
|
559 |
},
|
560 |
"require": {
|
566 |
"symfony/debug": "^2.7",
|
567 |
"symfony/phpunit-bridge": "^3.4.19|^4.1.8"
|
568 |
},
|
569 |
+
"time": "2019-02-27T07:39:35+00:00",
|
570 |
"type": "library",
|
571 |
"extra": {
|
572 |
"branch-alias": {
|
573 |
+
"dev-master": "1.38-dev"
|
574 |
}
|
575 |
},
|
576 |
"installation-source": "source",
|
vendor/symfony/polyfill-ctype/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
Copyright (c) 2018 Fabien Potencier
|
2 |
|
3 |
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4 |
of this software and associated documentation files (the "Software"), to deal
|
1 |
+
Copyright (c) 2018-2019 Fabien Potencier
|
2 |
|
3 |
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4 |
of this software and associated documentation files (the "Software"), to deal
|
vendor/symfony/polyfill-ctype/composer.json
CHANGED
@@ -28,7 +28,7 @@
|
|
28 |
"minimum-stability": "dev",
|
29 |
"extra": {
|
30 |
"branch-alias": {
|
31 |
-
"dev-master": "1.
|
32 |
}
|
33 |
}
|
34 |
}
|
28 |
"minimum-stability": "dev",
|
29 |
"extra": {
|
30 |
"branch-alias": {
|
31 |
+
"dev-master": "1.11-dev"
|
32 |
}
|
33 |
}
|
34 |
}
|
vendor/twig/twig/.php_cs.dist
CHANGED
@@ -5,11 +5,13 @@ return PhpCsFixer\Config::create()
|
|
5 |
'@Symfony' => true,
|
6 |
'@Symfony:risky' => true,
|
7 |
'array_syntax' => ['syntax' => 'short'],
|
8 |
-
'php_unit_fqcn_annotation' =>
|
9 |
'no_unreachable_default_argument_value' => false,
|
10 |
'braces' => ['allow_single_line_closure' => true],
|
11 |
'heredoc_to_nowdoc' => false,
|
12 |
-
'
|
|
|
|
|
13 |
])
|
14 |
->setRiskyAllowed(true)
|
15 |
->setFinder(PhpCsFixer\Finder::create()->in(__DIR__))
|
5 |
'@Symfony' => true,
|
6 |
'@Symfony:risky' => true,
|
7 |
'array_syntax' => ['syntax' => 'short'],
|
8 |
+
'php_unit_fqcn_annotation' => true,
|
9 |
'no_unreachable_default_argument_value' => false,
|
10 |
'braces' => ['allow_single_line_closure' => true],
|
11 |
'heredoc_to_nowdoc' => false,
|
12 |
+
'ordered_imports' => true,
|
13 |
+
'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
|
14 |
+
'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'all'],
|
15 |
])
|
16 |
->setRiskyAllowed(true)
|
17 |
->setFinder(PhpCsFixer\Finder::create()->in(__DIR__))
|
vendor/twig/twig/.travis.yml
CHANGED
@@ -15,7 +15,6 @@ php:
|
|
15 |
- 7.1
|
16 |
- 7.2
|
17 |
- 7.3
|
18 |
-
- nightly
|
19 |
|
20 |
env:
|
21 |
- TWIG_EXT=no
|
15 |
- 7.1
|
16 |
- 7.2
|
17 |
- 7.3
|
|
|
18 |
|
19 |
env:
|
20 |
- TWIG_EXT=no
|
vendor/twig/twig/CHANGELOG
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
-
* 1.
|
2 |
|
3 |
-
*
|
4 |
|
5 |
* 1.37.1 (2019-01-14)
|
6 |
|
1 |
+
* 1.38.0 (2019-XX-XX)
|
2 |
|
3 |
+
* changed internal code to use the namespaced classes as much as possible
|
4 |
|
5 |
* 1.37.1 (2019-01-14)
|
6 |
|
vendor/twig/twig/composer.json
CHANGED
@@ -23,9 +23,6 @@
|
|
23 |
"role": "Project Founder"
|
24 |
}
|
25 |
],
|
26 |
-
"support": {
|
27 |
-
"forum": "https://groups.google.com/forum/#!forum/twig-users"
|
28 |
-
},
|
29 |
"require": {
|
30 |
"php": ">=5.4.0",
|
31 |
"symfony/polyfill-ctype": "^1.8"
|
@@ -45,7 +42,7 @@
|
|
45 |
},
|
46 |
"extra": {
|
47 |
"branch-alias": {
|
48 |
-
"dev-master": "1.
|
49 |
}
|
50 |
}
|
51 |
}
|
23 |
"role": "Project Founder"
|
24 |
}
|
25 |
],
|
|
|
|
|
|
|
26 |
"require": {
|
27 |
"php": ">=5.4.0",
|
28 |
"symfony/polyfill-ctype": "^1.8"
|
42 |
},
|
43 |
"extra": {
|
44 |
"branch-alias": {
|
45 |
+
"dev-master": "1.38-dev"
|
46 |
}
|
47 |
}
|
48 |
}
|
vendor/twig/twig/doc/advanced.rst
CHANGED
@@ -114,7 +114,7 @@ Globals
|
|
114 |
A global variable is like any other template variable, except that it's
|
115 |
available in all templates and macros::
|
116 |
|
117 |
-
$twig = new
|
118 |
$twig->addGlobal('text', new Text());
|
119 |
|
120 |
You can then use the ``text`` variable anywhere in a template:
|
@@ -129,29 +129,29 @@ Filters
|
|
129 |
Creating a filter is as simple as associating a name with a PHP callable::
|
130 |
|
131 |
// an anonymous function
|
132 |
-
$filter = new
|
133 |
return str_rot13($string);
|
134 |
});
|
135 |
|
136 |
// or a simple PHP function
|
137 |
-
$filter = new
|
138 |
|
139 |
// or a class static method
|
140 |
-
$filter = new
|
141 |
-
$filter = new
|
142 |
|
143 |
// or a class method
|
144 |
-
$filter = new
|
145 |
// the one below needs a runtime implementation (see below for more information)
|
146 |
-
$filter = new
|
147 |
|
148 |
-
The first argument passed to the ``
|
149 |
of the filter you will use in templates and the second one is the PHP callable
|
150 |
to associate with it.
|
151 |
|
152 |
Then, add the filter to your Twig environment::
|
153 |
|
154 |
-
$twig = new
|
155 |
$twig->addFilter($filter);
|
156 |
|
157 |
And here is how to use it in a template:
|
@@ -178,10 +178,10 @@ is compiled to something like the following::
|
|
178 |
<?php echo strtolower('TWIG') ?>
|
179 |
<?php echo twig_date_format_filter($now, 'd/m/Y') ?>
|
180 |
|
181 |
-
The ``
|
182 |
argument::
|
183 |
|
184 |
-
$filter = new
|
185 |
|
186 |
Environment-aware Filters
|
187 |
~~~~~~~~~~~~~~~~~~~~~~~~~
|
@@ -190,7 +190,7 @@ If you want to access the current environment instance in your filter, set the
|
|
190 |
``needs_environment`` option to ``true``; Twig will pass the current
|
191 |
environment as the first argument to the filter call::
|
192 |
|
193 |
-
$filter = new
|
194 |
// get the current charset for instance
|
195 |
$charset = $env->getCharset();
|
196 |
|
@@ -205,11 +205,11 @@ If you want to access the current context in your filter, set the
|
|
205 |
the first argument to the filter call (or the second one if
|
206 |
``needs_environment`` is also set to ``true``)::
|
207 |
|
208 |
-
$filter = new
|
209 |
// ...
|
210 |
}, ['needs_context' => true]);
|
211 |
|
212 |
-
$filter = new
|
213 |
// ...
|
214 |
}, ['needs_context' => true, 'needs_environment' => true]);
|
215 |
|
@@ -221,14 +221,14 @@ before printing. If your filter acts as an escaper (or explicitly outputs HTML
|
|
221 |
or JavaScript code), you will want the raw output to be printed. In such a
|
222 |
case, set the ``is_safe`` option::
|
223 |
|
224 |
-
$filter = new
|
225 |
|
226 |
Some filters may need to work on input that is already escaped or safe, for
|
227 |
example when adding (safe) HTML tags to originally unsafe output. In such a
|
228 |
case, set the ``pre_escape`` option to escape the input data before it is run
|
229 |
through your filter::
|
230 |
|
231 |
-
$filter = new
|
232 |
|
233 |
Variadic Filters
|
234 |
~~~~~~~~~~~~~~~~
|
@@ -240,12 +240,13 @@ When a filter should accept an arbitrary number of arguments, set the
|
|
240 |
``is_variadic`` option to ``true``; Twig will pass the extra arguments as the
|
241 |
last argument to the filter call as an array::
|
242 |
|
243 |
-
$filter = new
|
244 |
// ...
|
245 |
}, ['is_variadic' => true]);
|
246 |
|
247 |
-
Be warned that named arguments passed to a variadic
|
248 |
-
for validity as they will automatically end up in the
|
|
|
249 |
|
250 |
Dynamic Filters
|
251 |
~~~~~~~~~~~~~~~
|
@@ -253,7 +254,7 @@ Dynamic Filters
|
|
253 |
A filter name containing the special ``*`` character is a dynamic filter as
|
254 |
the ``*`` can be any string::
|
255 |
|
256 |
-
$filter = new
|
257 |
// ...
|
258 |
});
|
259 |
|
@@ -264,7 +265,7 @@ The following filters will be matched by the above defined dynamic filter:
|
|
264 |
|
265 |
A dynamic filter can define more than one dynamic parts::
|
266 |
|
267 |
-
$filter = new
|
268 |
// ...
|
269 |
});
|
270 |
|
@@ -283,7 +284,7 @@ You can mark a filter as being deprecated by setting the ``deprecated`` option
|
|
283 |
to ``true``. You can also give an alternative filter that replaces the
|
284 |
deprecated one when that makes sense::
|
285 |
|
286 |
-
$filter = new
|
287 |
// ...
|
288 |
}, ['deprecated' => true, 'alternative' => 'new_one']);
|
289 |
|
@@ -294,10 +295,10 @@ Functions
|
|
294 |
---------
|
295 |
|
296 |
Functions are defined in the exact same way as filters, but you need to create
|
297 |
-
an instance of
|
298 |
|
299 |
-
$twig = new
|
300 |
-
$function = new
|
301 |
// ...
|
302 |
});
|
303 |
$twig->addFunction($function);
|
@@ -309,10 +310,10 @@ Tests
|
|
309 |
-----
|
310 |
|
311 |
Tests are defined in the exact same way as filters and functions, but you need
|
312 |
-
to create an instance of
|
313 |
|
314 |
-
$twig = new
|
315 |
-
$test = new
|
316 |
// ...
|
317 |
});
|
318 |
$twig->addTest($test);
|
@@ -321,8 +322,8 @@ Tests allow you to create custom application specific logic for evaluating
|
|
321 |
boolean conditions. As a simple example, let's create a Twig test that checks if
|
322 |
objects are 'red'::
|
323 |
|
324 |
-
$twig = new
|
325 |
-
$test = new
|
326 |
if (isset($value->color) && $value->color == 'red') {
|
327 |
return true;
|
328 |
}
|
@@ -339,16 +340,16 @@ When creating tests you can use the ``node_class`` option to provide custom test
|
|
339 |
compilation. This is useful if your test can be compiled into PHP primitives.
|
340 |
This is used by many of the tests built into Twig::
|
341 |
|
342 |
-
$twig = new
|
343 |
-
$test = new
|
344 |
'odd',
|
345 |
null,
|
346 |
-
['node_class' => '
|
347 |
$twig->addTest($test);
|
348 |
|
349 |
-
class Twig_Node_Expression_Test_Odd extends
|
350 |
{
|
351 |
-
public function compile(
|
352 |
{
|
353 |
$compiler
|
354 |
->raw('(')
|
@@ -382,9 +383,47 @@ Tags
|
|
382 |
----
|
383 |
|
384 |
One of the most exciting features of a template engine like Twig is the
|
385 |
-
possibility to define new language constructs
|
386 |
feature as you need to understand how Twig's internals work.
|
387 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
388 |
Let's create a simple ``set`` tag that allows the definition of simple
|
389 |
variables from within a template. The tag can be used like follows:
|
390 |
|
@@ -415,9 +454,9 @@ Registering a new tag
|
|
415 |
~~~~~~~~~~~~~~~~~~~~~
|
416 |
|
417 |
Adding a tag is as simple as calling the ``addTokenParser`` method on the
|
418 |
-
``
|
419 |
|
420 |
-
$twig = new
|
421 |
$twig->addTokenParser(new Project_Set_TokenParser());
|
422 |
|
423 |
Defining a Token Parser
|
@@ -425,17 +464,17 @@ Defining a Token Parser
|
|
425 |
|
426 |
Now, let's see the actual code of this class::
|
427 |
|
428 |
-
class Project_Set_TokenParser extends
|
429 |
{
|
430 |
-
public function parse(
|
431 |
{
|
432 |
$parser = $this->parser;
|
433 |
$stream = $parser->getStream();
|
434 |
|
435 |
-
$name = $stream->expect(
|
436 |
-
$stream->expect(
|
437 |
$value = $parser->getExpressionParser()->parseExpression();
|
438 |
-
$stream->expect(
|
439 |
|
440 |
return new Project_Set_Node($name, $value, $token->getLine(), $this->getTag());
|
441 |
}
|
@@ -449,7 +488,7 @@ Now, let's see the actual code of this class::
|
|
449 |
The ``getTag()`` method must return the tag we want to parse, here ``set``.
|
450 |
|
451 |
The ``parse()`` method is invoked whenever the parser encounters a ``set``
|
452 |
-
tag. It should return a ``
|
453 |
``Project_Set_Node`` calls creating is explained in the next section).
|
454 |
|
455 |
The parsing process is simplified thanks to a bunch of methods you can call
|
@@ -482,14 +521,14 @@ Defining a Node
|
|
482 |
|
483 |
The ``Project_Set_Node`` class itself is rather simple::
|
484 |
|
485 |
-
class Project_Set_Node extends
|
486 |
{
|
487 |
-
public function __construct($name,
|
488 |
{
|
489 |
parent::__construct(['value' => $value], ['name' => $name], $line, $tag);
|
490 |
}
|
491 |
|
492 |
-
public function compile(
|
493 |
{
|
494 |
$compiler
|
495 |
->addDebugInfo($this)
|
@@ -513,15 +552,15 @@ developer generate beautiful and readable PHP code:
|
|
513 |
* ``string()``: Writes a quoted string.
|
514 |
|
515 |
* ``repr()``: Writes a PHP representation of a given value (see
|
516 |
-
``
|
517 |
|
518 |
* ``addDebugInfo()``: Adds the line of the original template file related to
|
519 |
the current node as a comment.
|
520 |
|
521 |
-
* ``indent()``: Indents the generated code (see ``
|
522 |
usage example).
|
523 |
|
524 |
-
* ``outdent()``: Outdents the generated code (see ``
|
525 |
usage example).
|
526 |
|
527 |
.. _creating_extensions:
|
@@ -557,9 +596,9 @@ An extension is a class that implements the following interface::
|
|
557 |
*
|
558 |
* This is where you can load some file that contains filter functions for instance.
|
559 |
*
|
560 |
-
* @deprecated since 1.23 (to be removed in 2.0), implement
|
561 |
*/
|
562 |
-
function initRuntime(
|
563 |
|
564 |
/**
|
565 |
* Returns the token parser instances to add to the existing list.
|
@@ -571,28 +610,28 @@ An extension is a class that implements the following interface::
|
|
571 |
/**
|
572 |
* Returns the node visitor instances to add to the existing list.
|
573 |
*
|
574 |
-
* @return
|
575 |
*/
|
576 |
function getNodeVisitors();
|
577 |
|
578 |
/**
|
579 |
* Returns a list of filters to add to the existing list.
|
580 |
*
|
581 |
-
* @return
|
582 |
*/
|
583 |
function getFilters();
|
584 |
|
585 |
/**
|
586 |
* Returns a list of tests to add to the existing list.
|
587 |
*
|
588 |
-
* @return
|
589 |
*/
|
590 |
function getTests();
|
591 |
|
592 |
/**
|
593 |
* Returns a list of functions to add to the existing list.
|
594 |
*
|
595 |
-
* @return
|
596 |
*/
|
597 |
function getFunctions();
|
598 |
|
@@ -608,7 +647,7 @@ An extension is a class that implements the following interface::
|
|
608 |
*
|
609 |
* @return array An array of global variables
|
610 |
*
|
611 |
-
* @deprecated since 1.23 (to be removed in 2.0), implement
|
612 |
*/
|
613 |
function getGlobals();
|
614 |
|
@@ -623,10 +662,10 @@ An extension is a class that implements the following interface::
|
|
623 |
}
|
624 |
|
625 |
To keep your extension class clean and lean, inherit from the built-in
|
626 |
-
``
|
627 |
empty implementations for all methods:
|
628 |
|
629 |
-
class Project_Twig_Extension extends
|
630 |
{
|
631 |
}
|
632 |
|
@@ -644,7 +683,7 @@ extensions must be registered explicitly to be available in your templates.
|
|
644 |
You can register an extension by using the ``addExtension()`` method on your
|
645 |
main ``Environment`` object::
|
646 |
|
647 |
-
$twig = new
|
648 |
$twig->addExtension(new Project_Twig_Extension());
|
649 |
|
650 |
.. tip::
|
@@ -657,7 +696,7 @@ Globals
|
|
657 |
Global variables can be registered in an extension via the ``getGlobals()``
|
658 |
method::
|
659 |
|
660 |
-
class Project_Twig_Extension extends
|
661 |
{
|
662 |
public function getGlobals()
|
663 |
{
|
@@ -675,12 +714,12 @@ Functions
|
|
675 |
Functions can be registered in an extension via the ``getFunctions()``
|
676 |
method::
|
677 |
|
678 |
-
class Project_Twig_Extension extends
|
679 |
{
|
680 |
public function getFunctions()
|
681 |
{
|
682 |
return [
|
683 |
-
new
|
684 |
];
|
685 |
}
|
686 |
|
@@ -694,12 +733,12 @@ To add a filter to an extension, you need to override the ``getFilters()``
|
|
694 |
method. This method must return an array of filters to add to the Twig
|
695 |
environment::
|
696 |
|
697 |
-
class Project_Twig_Extension extends
|
698 |
{
|
699 |
public function getFilters()
|
700 |
{
|
701 |
return [
|
702 |
-
new
|
703 |
];
|
704 |
}
|
705 |
|
@@ -713,7 +752,7 @@ Adding a tag in an extension can be done by overriding the
|
|
713 |
``getTokenParsers()`` method. This method must return an array of tags to add
|
714 |
to the Twig environment::
|
715 |
|
716 |
-
class Project_Twig_Extension extends
|
717 |
{
|
718 |
public function getTokenParsers()
|
719 |
{
|
@@ -733,17 +772,17 @@ Operators
|
|
733 |
The ``getOperators()`` methods lets you add new operators. Here is how to add
|
734 |
``!``, ``||``, and ``&&`` operators::
|
735 |
|
736 |
-
class Project_Twig_Extension extends
|
737 |
{
|
738 |
public function getOperators()
|
739 |
{
|
740 |
return [
|
741 |
[
|
742 |
-
'!' => ['precedence' => 50, 'class' => '
|
743 |
],
|
744 |
[
|
745 |
-
'||' => ['precedence' => 10, 'class' => '
|
746 |
-
'&&' => ['precedence' => 15, 'class' => '
|
747 |
],
|
748 |
];
|
749 |
}
|
@@ -756,12 +795,12 @@ Tests
|
|
756 |
|
757 |
The ``getTests()`` method lets you add new test functions::
|
758 |
|
759 |
-
class Project_Twig_Extension extends
|
760 |
{
|
761 |
public function getTests()
|
762 |
{
|
763 |
return [
|
764 |
-
new
|
765 |
];
|
766 |
}
|
767 |
|
@@ -785,7 +824,7 @@ any valid PHP callable:
|
|
785 |
|
786 |
The simplest way to use methods is to define them on the extension itself::
|
787 |
|
788 |
-
class Project_Twig_Extension extends
|
789 |
{
|
790 |
private $rot13Provider;
|
791 |
|
@@ -797,7 +836,7 @@ The simplest way to use methods is to define them on the extension itself::
|
|
797 |
public function getFunctions()
|
798 |
{
|
799 |
return [
|
800 |
-
new
|
801 |
];
|
802 |
}
|
803 |
|
@@ -812,11 +851,11 @@ depend on runtime dependencies even if they are not needed (think for instance
|
|
812 |
as a dependency that connects to a database engine).
|
813 |
|
814 |
As of Twig 1.26, you can easily decouple the extension definitions from their
|
815 |
-
runtime implementations by registering a ``
|
816 |
instance on the environment that knows how to instantiate such runtime classes
|
817 |
(runtime classes must be autoload-able)::
|
818 |
|
819 |
-
class RuntimeLoader implements
|
820 |
{
|
821 |
public function load($class)
|
822 |
{
|
@@ -836,7 +875,7 @@ instance on the environment that knows how to instantiate such runtime classes
|
|
836 |
.. note::
|
837 |
|
838 |
As of Twig 1.32, Twig comes with a PSR-11 compatible runtime loader
|
839 |
-
(``
|
840 |
|
841 |
It is now possible to move the runtime logic to a new
|
842 |
``Project_Twig_RuntimeExtension`` class and use it directly in the extension::
|
@@ -856,14 +895,14 @@ It is now possible to move the runtime logic to a new
|
|
856 |
}
|
857 |
}
|
858 |
|
859 |
-
class Project_Twig_Extension extends
|
860 |
{
|
861 |
public function getFunctions()
|
862 |
{
|
863 |
return [
|
864 |
-
new
|
865 |
// or
|
866 |
-
new
|
867 |
];
|
868 |
}
|
869 |
}
|
@@ -875,12 +914,12 @@ To overload an already defined filter, test, operator, global variable, or
|
|
875 |
function, re-define it in an extension and register it **as late as
|
876 |
possible** (order matters)::
|
877 |
|
878 |
-
class MyCoreExtension extends
|
879 |
{
|
880 |
public function getFilters()
|
881 |
{
|
882 |
return [
|
883 |
-
new
|
884 |
];
|
885 |
}
|
886 |
|
@@ -890,16 +929,16 @@ possible** (order matters)::
|
|
890 |
}
|
891 |
}
|
892 |
|
893 |
-
$twig = new
|
894 |
$twig->addExtension(new MyCoreExtension());
|
895 |
|
896 |
Here, we have overloaded the built-in ``date`` filter with a custom one.
|
897 |
|
898 |
-
If you do the same on the ``
|
899 |
precedence over any other registered extensions::
|
900 |
|
901 |
-
$twig = new
|
902 |
-
$twig->addFilter(new
|
903 |
// do something different from the built-in date filter
|
904 |
}));
|
905 |
// the date filter will come from the above registration, not
|
@@ -934,7 +973,7 @@ following file structure in your test directory::
|
|
934 |
|
935 |
The ``IntegrationTest.php`` file should look like this::
|
936 |
|
937 |
-
class Project_Tests_IntegrationTest extends
|
938 |
{
|
939 |
public function getExtensions()
|
940 |
{
|
@@ -957,7 +996,7 @@ Node Tests
|
|
957 |
~~~~~~~~~~
|
958 |
|
959 |
Testing the node visitors can be complex, so extend your test cases from
|
960 |
-
|
961 |
`tests/Twig/Node`_ directory.
|
962 |
|
963 |
.. _`rot13`: https://secure.php.net/manual/en/function.str-rot13.php
|
114 |
A global variable is like any other template variable, except that it's
|
115 |
available in all templates and macros::
|
116 |
|
117 |
+
$twig = new \Twig\Environment($loader);
|
118 |
$twig->addGlobal('text', new Text());
|
119 |
|
120 |
You can then use the ``text`` variable anywhere in a template:
|
129 |
Creating a filter is as simple as associating a name with a PHP callable::
|
130 |
|
131 |
// an anonymous function
|
132 |
+
$filter = new \Twig\TwigFilter('rot13', function ($string) {
|
133 |
return str_rot13($string);
|
134 |
});
|
135 |
|
136 |
// or a simple PHP function
|
137 |
+
$filter = new \Twig\TwigFilter('rot13', 'str_rot13');
|
138 |
|
139 |
// or a class static method
|
140 |
+
$filter = new \Twig\TwigFilter('rot13', ['SomeClass', 'rot13Filter']);
|
141 |
+
$filter = new \Twig\TwigFilter('rot13', 'SomeClass::rot13Filter');
|
142 |
|
143 |
// or a class method
|
144 |
+
$filter = new \Twig\TwigFilter('rot13', [$this, 'rot13Filter']);
|
145 |
// the one below needs a runtime implementation (see below for more information)
|
146 |
+
$filter = new \Twig\TwigFilter('rot13', ['SomeClass', 'rot13Filter']);
|
147 |
|
148 |
+
The first argument passed to the ``\Twig\TwigFilter`` constructor is the name
|
149 |
of the filter you will use in templates and the second one is the PHP callable
|
150 |
to associate with it.
|
151 |
|
152 |
Then, add the filter to your Twig environment::
|
153 |
|
154 |
+
$twig = new \Twig\Environment($loader);
|
155 |
$twig->addFilter($filter);
|
156 |
|
157 |
And here is how to use it in a template:
|
178 |
<?php echo strtolower('TWIG') ?>
|
179 |
<?php echo twig_date_format_filter($now, 'd/m/Y') ?>
|
180 |
|
181 |
+
The ``\Twig\TwigFilter`` class takes an array of options as its last
|
182 |
argument::
|
183 |
|
184 |
+
$filter = new \Twig\TwigFilter('rot13', 'str_rot13', $options);
|
185 |
|
186 |
Environment-aware Filters
|
187 |
~~~~~~~~~~~~~~~~~~~~~~~~~
|
190 |
``needs_environment`` option to ``true``; Twig will pass the current
|
191 |
environment as the first argument to the filter call::
|
192 |
|
193 |
+
$filter = new \Twig\TwigFilter('rot13', function (Twig_Environment $env, $string) {
|
194 |
// get the current charset for instance
|
195 |
$charset = $env->getCharset();
|
196 |
|
205 |
the first argument to the filter call (or the second one if
|
206 |
``needs_environment`` is also set to ``true``)::
|
207 |
|
208 |
+
$filter = new \Twig\TwigFilter('rot13', function ($context, $string) {
|
209 |
// ...
|
210 |
}, ['needs_context' => true]);
|
211 |
|
212 |
+
$filter = new \Twig\TwigFilter('rot13', function (Twig_Environment $env, $context, $string) {
|
213 |
// ...
|
214 |
}, ['needs_context' => true, 'needs_environment' => true]);
|
215 |
|
221 |
or JavaScript code), you will want the raw output to be printed. In such a
|
222 |
case, set the ``is_safe`` option::
|
223 |
|
224 |
+
$filter = new \Twig\TwigFilter('nl2br', 'nl2br', ['is_safe' => ['html']]);
|
225 |
|
226 |
Some filters may need to work on input that is already escaped or safe, for
|
227 |
example when adding (safe) HTML tags to originally unsafe output. In such a
|
228 |
case, set the ``pre_escape`` option to escape the input data before it is run
|
229 |
through your filter::
|
230 |
|
231 |
+
$filter = new \Twig\TwigFilter('somefilter', 'somefilter', ['pre_escape' => 'html', 'is_safe' => ['html']]);
|
232 |
|
233 |
Variadic Filters
|
234 |
~~~~~~~~~~~~~~~~
|
240 |
``is_variadic`` option to ``true``; Twig will pass the extra arguments as the
|
241 |
last argument to the filter call as an array::
|
242 |
|
243 |
+
$filter = new \Twig\TwigFilter('thumbnail', function ($file, array $options = []) {
|
244 |
// ...
|
245 |
}, ['is_variadic' => true]);
|
246 |
|
247 |
+
Be warned that :ref:`named arguments <named-arguments>` passed to a variadic
|
248 |
+
filter cannot be checked for validity as they will automatically end up in the
|
249 |
+
option array.
|
250 |
|
251 |
Dynamic Filters
|
252 |
~~~~~~~~~~~~~~~
|
254 |
A filter name containing the special ``*`` character is a dynamic filter as
|
255 |
the ``*`` can be any string::
|
256 |
|
257 |
+
$filter = new \Twig\TwigFilter('*_path', function ($name, $arguments) {
|
258 |
// ...
|
259 |
});
|
260 |
|
265 |
|
266 |
A dynamic filter can define more than one dynamic parts::
|
267 |
|
268 |
+
$filter = new \Twig\TwigFilter('*_path_*', function ($name, $suffix, $arguments) {
|
269 |
// ...
|
270 |
});
|
271 |
|
284 |
to ``true``. You can also give an alternative filter that replaces the
|
285 |
deprecated one when that makes sense::
|
286 |
|
287 |
+
$filter = new \Twig\TwigFilter('obsolete', function () {
|
288 |
// ...
|
289 |
}, ['deprecated' => true, 'alternative' => 'new_one']);
|
290 |
|
295 |
---------
|
296 |
|
297 |
Functions are defined in the exact same way as filters, but you need to create
|
298 |
+
an instance of ``\Twig\TwigFunction``::
|
299 |
|
300 |
+
$twig = new \Twig\Environment($loader);
|
301 |
+
$function = new \Twig\TwigFunction('function_name', function () {
|
302 |
// ...
|
303 |
});
|
304 |
$twig->addFunction($function);
|
310 |
-----
|
311 |
|
312 |
Tests are defined in the exact same way as filters and functions, but you need
|
313 |
+
to create an instance of ``\Twig\TwigTest``::
|
314 |
|
315 |
+
$twig = new \Twig\Environment($loader);
|
316 |
+
$test = new \Twig\TwigTest('test_name', function () {
|
317 |
// ...
|
318 |
});
|
319 |
$twig->addTest($test);
|
322 |
boolean conditions. As a simple example, let's create a Twig test that checks if
|
323 |
objects are 'red'::
|
324 |
|
325 |
+
$twig = new \Twig\Environment($loader);
|
326 |
+
$test = new \Twig\TwigTest('red', function ($value) {
|
327 |
if (isset($value->color) && $value->color == 'red') {
|
328 |
return true;
|
329 |
}
|
340 |
compilation. This is useful if your test can be compiled into PHP primitives.
|
341 |
This is used by many of the tests built into Twig::
|
342 |
|
343 |
+
$twig = new \Twig\Environment($loader);
|
344 |
+
$test = new \Twig\TwigTest(
|
345 |
'odd',
|
346 |
null,
|
347 |
+
['node_class' => '\Twig\Node\Expression\Test\OddTest']);
|
348 |
$twig->addTest($test);
|
349 |
|
350 |
+
class Twig_Node_Expression_Test_Odd extends \Twig\Node\Expression\TestExpression
|
351 |
{
|
352 |
+
public function compile(\Twig\Compiler $compiler)
|
353 |
{
|
354 |
$compiler
|
355 |
->raw('(')
|
383 |
----
|
384 |
|
385 |
One of the most exciting features of a template engine like Twig is the
|
386 |
+
possibility to define new **language constructs**. This is also the most complex
|
387 |
feature as you need to understand how Twig's internals work.
|
388 |
|
389 |
+
Most of the time though, a tag is not needed:
|
390 |
+
|
391 |
+
* If your tag generates some output, use a **function** instead.
|
392 |
+
|
393 |
+
* If your tag modifies some content and returns it, use a **filter** instead.
|
394 |
+
|
395 |
+
For instance, if you want to create a tag that converts a Markdown formatted
|
396 |
+
text to HTML, create a ``markdown`` filter instead:
|
397 |
+
|
398 |
+
.. code-block:: jinja
|
399 |
+
|
400 |
+
{{ '**markdown** text'|markdown }}
|
401 |
+
|
402 |
+
If you want use this filter on large amounts of text, wrap it with the
|
403 |
+
:doc:`filter <tags/filter>` tag:
|
404 |
+
|
405 |
+
.. code-block:: jinja
|
406 |
+
|
407 |
+
{% filter markdown %}
|
408 |
+
Title
|
409 |
+
=====
|
410 |
+
|
411 |
+
Much better than creating a tag as you can **compose** filters.
|
412 |
+
{% endfilter %}
|
413 |
+
|
414 |
+
* If your tag does not output anything, but only exists because of a side
|
415 |
+
effect, create a **function** that returns nothing and call it via the
|
416 |
+
:doc:`filter <tags/do>` tag.
|
417 |
+
|
418 |
+
For instance, if you want to create a tag that logs text, create a ``log``
|
419 |
+
function instead and call it via the :doc:`do <tags/do>` tag:
|
420 |
+
|
421 |
+
.. code-block:: jinja
|
422 |
+
|
423 |
+
{% do log('Log some things') %}
|
424 |
+
|
425 |
+
If you still want to create a tag for a new language construct, great!
|
426 |
+
|
427 |
Let's create a simple ``set`` tag that allows the definition of simple
|
428 |
variables from within a template. The tag can be used like follows:
|
429 |
|
454 |
~~~~~~~~~~~~~~~~~~~~~
|
455 |
|
456 |
Adding a tag is as simple as calling the ``addTokenParser`` method on the
|
457 |
+
``\Twig\Environment`` instance::
|
458 |
|
459 |
+
$twig = new \Twig\Environment($loader);
|
460 |
$twig->addTokenParser(new Project_Set_TokenParser());
|
461 |
|
462 |
Defining a Token Parser
|
464 |
|
465 |
Now, let's see the actual code of this class::
|
466 |
|
467 |
+
class Project_Set_TokenParser extends \Twig\TokenParser\AbstractTokenParser
|
468 |
{
|
469 |
+
public function parse(\Twig\Token $token)
|
470 |
{
|
471 |
$parser = $this->parser;
|
472 |
$stream = $parser->getStream();
|
473 |
|
474 |
+
$name = $stream->expect(\Twig\Token::NAME_TYPE)->getValue();
|
475 |
+
$stream->expect(\Twig\Token::OPERATOR_TYPE, '=');
|
476 |
$value = $parser->getExpressionParser()->parseExpression();
|
477 |
+
$stream->expect(\Twig\Token::BLOCK_END_TYPE);
|
478 |
|
479 |
return new Project_Set_Node($name, $value, $token->getLine(), $this->getTag());
|
480 |
}
|
488 |
The ``getTag()`` method must return the tag we want to parse, here ``set``.
|
489 |
|
490 |
The ``parse()`` method is invoked whenever the parser encounters a ``set``
|
491 |
+
tag. It should return a ``\Twig\Node\Node`` instance that represents the node (the
|
492 |
``Project_Set_Node`` calls creating is explained in the next section).
|
493 |
|
494 |
The parsing process is simplified thanks to a bunch of methods you can call
|
521 |
|
522 |
The ``Project_Set_Node`` class itself is rather simple::
|
523 |
|
524 |
+
class Project_Set_Node extends \Twig\Node\Node
|
525 |
{
|
526 |
+
public function __construct($name, \Twig\Node\Expression\AbstractExpression $value, $line, $tag = null)
|
527 |
{
|
528 |
parent::__construct(['value' => $value], ['name' => $name], $line, $tag);
|
529 |
}
|
530 |
|
531 |
+
public function compile(\Twig\Compiler $compiler)
|
532 |
{
|
533 |
$compiler
|
534 |
->addDebugInfo($this)
|
552 |
* ``string()``: Writes a quoted string.
|
553 |
|
554 |
* ``repr()``: Writes a PHP representation of a given value (see
|
555 |
+
``\Twig\Node\ForNode`` for a usage example).
|
556 |
|
557 |
* ``addDebugInfo()``: Adds the line of the original template file related to
|
558 |
the current node as a comment.
|
559 |
|
560 |
+
* ``indent()``: Indents the generated code (see ``\Twig\Node\BlockNode`` for a
|
561 |
usage example).
|
562 |
|
563 |
+
* ``outdent()``: Outdents the generated code (see ``\Twig\Node\BlockNode`` for a
|
564 |
usage example).
|
565 |
|
566 |
.. _creating_extensions:
|
596 |
*
|
597 |
* This is where you can load some file that contains filter functions for instance.
|
598 |
*
|
599 |
+
* @deprecated since 1.23 (to be removed in 2.0), implement \Twig\Extension\InitRuntimeInterface instead
|
600 |
*/
|
601 |
+
function initRuntime(\Twig\Environment $environment);
|
602 |
|
603 |
/**
|
604 |
* Returns the token parser instances to add to the existing list.
|
610 |
/**
|
611 |
* Returns the node visitor instances to add to the existing list.
|
612 |
*
|
613 |
+
* @return \Twig\NodeVisitor\NodeVisitorInterface[]
|
614 |
*/
|
615 |
function getNodeVisitors();
|
616 |
|
617 |
/**
|
618 |
* Returns a list of filters to add to the existing list.
|
619 |
*
|
620 |
+
* @return \Twig\TwigFilter[]
|
621 |
*/
|
622 |
function getFilters();
|
623 |
|
624 |
/**
|
625 |
* Returns a list of tests to add to the existing list.
|
626 |
*
|
627 |
+
* @return \Twig\TwigTest[]
|
628 |
*/
|
629 |
function getTests();
|
630 |
|
631 |
/**
|
632 |
* Returns a list of functions to add to the existing list.
|
633 |
*
|
634 |
+
* @return \Twig\TwigFunction[]
|
635 |
*/
|
636 |
function getFunctions();
|
637 |
|
647 |
*
|
648 |
* @return array An array of global variables
|
649 |
*
|
650 |
+
* @deprecated since 1.23 (to be removed in 2.0), implement \Twig\Extension\GlobalsInterface instead
|
651 |
*/
|
652 |
function getGlobals();
|
653 |
|
662 |
}
|
663 |
|
664 |
To keep your extension class clean and lean, inherit from the built-in
|
665 |
+
``\Twig\Extension\AbstractExtension`` class instead of implementing the interface as it provides
|
666 |
empty implementations for all methods:
|
667 |
|
668 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
669 |
{
|
670 |
}
|
671 |
|
683 |
You can register an extension by using the ``addExtension()`` method on your
|
684 |
main ``Environment`` object::
|
685 |
|
686 |
+
$twig = new \Twig\Environment($loader);
|
687 |
$twig->addExtension(new Project_Twig_Extension());
|
688 |
|
689 |
.. tip::
|
696 |
Global variables can be registered in an extension via the ``getGlobals()``
|
697 |
method::
|
698 |
|
699 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension implements \Twig\Extension\GlobalsInterface
|
700 |
{
|
701 |
public function getGlobals()
|
702 |
{
|
714 |
Functions can be registered in an extension via the ``getFunctions()``
|
715 |
method::
|
716 |
|
717 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
718 |
{
|
719 |
public function getFunctions()
|
720 |
{
|
721 |
return [
|
722 |
+
new \Twig\TwigFunction('lipsum', 'generate_lipsum'),
|
723 |
];
|
724 |
}
|
725 |
|
733 |
method. This method must return an array of filters to add to the Twig
|
734 |
environment::
|
735 |
|
736 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
737 |
{
|
738 |
public function getFilters()
|
739 |
{
|
740 |
return [
|
741 |
+
new \Twig\TwigFilter('rot13', 'str_rot13'),
|
742 |
];
|
743 |
}
|
744 |
|
752 |
``getTokenParsers()`` method. This method must return an array of tags to add
|
753 |
to the Twig environment::
|
754 |
|
755 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
756 |
{
|
757 |
public function getTokenParsers()
|
758 |
{
|
772 |
The ``getOperators()`` methods lets you add new operators. Here is how to add
|
773 |
``!``, ``||``, and ``&&`` operators::
|
774 |
|
775 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
776 |
{
|
777 |
public function getOperators()
|
778 |
{
|
779 |
return [
|
780 |
[
|
781 |
+
'!' => ['precedence' => 50, 'class' => '\Twig\Node\Expression\Unary\NotUnary'],
|
782 |
],
|
783 |
[
|
784 |
+
'||' => ['precedence' => 10, 'class' => '\Twig\Node\Expression\Binary\OrBinary', 'associativity' => \Twig\ExpressionParser::OPERATOR_LEFT],
|
785 |
+
'&&' => ['precedence' => 15, 'class' => '\Twig\Node\Expression\Binary\AndBinary', 'associativity' => \Twig\ExpressionParser::OPERATOR_LEFT],
|
786 |
],
|
787 |
];
|
788 |
}
|
795 |
|
796 |
The ``getTests()`` method lets you add new test functions::
|
797 |
|
798 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
799 |
{
|
800 |
public function getTests()
|
801 |
{
|
802 |
return [
|
803 |
+
new \Twig\TwigTest('even', 'twig_test_even'),
|
804 |
];
|
805 |
}
|
806 |
|
824 |
|
825 |
The simplest way to use methods is to define them on the extension itself::
|
826 |
|
827 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
828 |
{
|
829 |
private $rot13Provider;
|
830 |
|
836 |
public function getFunctions()
|
837 |
{
|
838 |
return [
|
839 |
+
new \Twig\TwigFunction('rot13', [$this, 'rot13']),
|
840 |
];
|
841 |
}
|
842 |
|
851 |
as a dependency that connects to a database engine).
|
852 |
|
853 |
As of Twig 1.26, you can easily decouple the extension definitions from their
|
854 |
+
runtime implementations by registering a ``\Twig\RuntimeLoader\RuntimeLoaderInterface``
|
855 |
instance on the environment that knows how to instantiate such runtime classes
|
856 |
(runtime classes must be autoload-able)::
|
857 |
|
858 |
+
class RuntimeLoader implements \Twig\RuntimeLoader\RuntimeLoaderInterface
|
859 |
{
|
860 |
public function load($class)
|
861 |
{
|
875 |
.. note::
|
876 |
|
877 |
As of Twig 1.32, Twig comes with a PSR-11 compatible runtime loader
|
878 |
+
(``\Twig\RuntimeLoader\ContainerRuntimeLoader``) that works on PHP 5.3+.
|
879 |
|
880 |
It is now possible to move the runtime logic to a new
|
881 |
``Project_Twig_RuntimeExtension`` class and use it directly in the extension::
|
895 |
}
|
896 |
}
|
897 |
|
898 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
899 |
{
|
900 |
public function getFunctions()
|
901 |
{
|
902 |
return [
|
903 |
+
new \Twig\TwigFunction('rot13', ['Project_Twig_RuntimeExtension', 'rot13']),
|
904 |
// or
|
905 |
+
new \Twig\TwigFunction('rot13', 'Project_Twig_RuntimeExtension::rot13'),
|
906 |
];
|
907 |
}
|
908 |
}
|
914 |
function, re-define it in an extension and register it **as late as
|
915 |
possible** (order matters)::
|
916 |
|
917 |
+
class MyCoreExtension extends \Twig\Extension\AbstractExtension
|
918 |
{
|
919 |
public function getFilters()
|
920 |
{
|
921 |
return [
|
922 |
+
new \Twig\TwigFilter('date', [$this, 'dateFilter']),
|
923 |
];
|
924 |
}
|
925 |
|
929 |
}
|
930 |
}
|
931 |
|
932 |
+
$twig = new \Twig\Environment($loader);
|
933 |
$twig->addExtension(new MyCoreExtension());
|
934 |
|
935 |
Here, we have overloaded the built-in ``date`` filter with a custom one.
|
936 |
|
937 |
+
If you do the same on the ``\Twig\Environment`` itself, beware that it takes
|
938 |
precedence over any other registered extensions::
|
939 |
|
940 |
+
$twig = new \Twig\Environment($loader);
|
941 |
+
$twig->addFilter(new \Twig\TwigFilter('date', function ($timestamp, $format = 'F j, Y H:i') {
|
942 |
// do something different from the built-in date filter
|
943 |
}));
|
944 |
// the date filter will come from the above registration, not
|
973 |
|
974 |
The ``IntegrationTest.php`` file should look like this::
|
975 |
|
976 |
+
class Project_Tests_IntegrationTest extends \Twig\Test\IntegrationTestCase
|
977 |
{
|
978 |
public function getExtensions()
|
979 |
{
|
996 |
~~~~~~~~~~
|
997 |
|
998 |
Testing the node visitors can be complex, so extend your test cases from
|
999 |
+
``\Twig\Test\NodeTestCase``. Examples can be found in the Twig repository
|
1000 |
`tests/Twig/Node`_ directory.
|
1001 |
|
1002 |
.. _`rot13`: https://secure.php.net/manual/en/function.str-rot13.php
|
vendor/twig/twig/doc/advanced_legacy.rst
CHANGED
@@ -115,7 +115,7 @@ Globals
|
|
115 |
A global variable is like any other template variable, except that it's
|
116 |
available in all templates and macros::
|
117 |
|
118 |
-
$twig = new
|
119 |
$twig->addGlobal('text', new Text());
|
120 |
|
121 |
You can then use the ``text`` variable anywhere in a template:
|
@@ -176,9 +176,9 @@ expected output:
|
|
176 |
{# should displays Gjvt #}
|
177 |
|
178 |
Adding a filter is as simple as calling the ``addFilter()`` method on the
|
179 |
-
``
|
180 |
|
181 |
-
$twig = new
|
182 |
$twig->addFilter('rot13', new Twig_Filter_Function('str_rot13'));
|
183 |
|
184 |
The second argument of ``addFilter()`` is an instance of ``Twig_Filter``.
|
@@ -232,7 +232,7 @@ if you want access to the current environment instance in your filter, set the
|
|
232 |
Twig will then pass the current environment as the first argument to the
|
233 |
filter call::
|
234 |
|
235 |
-
function twig_compute_rot13(
|
236 |
{
|
237 |
// get the current charset for instance
|
238 |
$charset = $env->getCharset();
|
@@ -311,15 +311,15 @@ compilation, the generated PHP code is roughly equivalent to:
|
|
311 |
<?php echo constant('DATE_W3C') ?>
|
312 |
|
313 |
Adding a function is similar to adding a filter. This can be done by calling the
|
314 |
-
``addFunction()`` method on the ``
|
315 |
|
316 |
-
$twig = new
|
317 |
$twig->addFunction('functionName', new Twig_Function_Function('someFunction'));
|
318 |
|
319 |
You can also expose extension methods as functions in your templates::
|
320 |
|
321 |
-
// $this is an object that implements
|
322 |
-
$twig = new
|
323 |
$twig->addFunction('otherFunction', new Twig_Function_Method($this, 'someMethod'));
|
324 |
|
325 |
Functions also support ``needs_environment`` and ``is_safe`` parameters.
|
@@ -395,9 +395,9 @@ Registering a new tag
|
|
395 |
~~~~~~~~~~~~~~~~~~~~~
|
396 |
|
397 |
Adding a tag is as simple as calling the ``addTokenParser`` method on the
|
398 |
-
``
|
399 |
|
400 |
-
$twig = new
|
401 |
$twig->addTokenParser(new Project_Set_TokenParser());
|
402 |
|
403 |
Defining a Token Parser
|
@@ -405,16 +405,16 @@ Defining a Token Parser
|
|
405 |
|
406 |
Now, let's see the actual code of this class::
|
407 |
|
408 |
-
class Project_Set_TokenParser extends
|
409 |
{
|
410 |
-
public function parse(
|
411 |
{
|
412 |
$lineno = $token->getLine();
|
413 |
-
$name = $this->parser->getStream()->expect(
|
414 |
-
$this->parser->getStream()->expect(
|
415 |
$value = $this->parser->getExpressionParser()->parseExpression();
|
416 |
|
417 |
-
$this->parser->getStream()->expect(
|
418 |
|
419 |
return new Project_Set_Node($name, $value, $lineno, $this->getTag());
|
420 |
}
|
@@ -428,7 +428,7 @@ Now, let's see the actual code of this class::
|
|
428 |
The ``getTag()`` method must return the tag we want to parse, here ``set``.
|
429 |
|
430 |
The ``parse()`` method is invoked whenever the parser encounters a ``set``
|
431 |
-
tag. It should return a ``
|
432 |
``Project_Set_Node`` calls creating is explained in the next section).
|
433 |
|
434 |
The parsing process is simplified thanks to a bunch of methods you can call
|
@@ -461,14 +461,14 @@ Defining a Node
|
|
461 |
|
462 |
The ``Project_Set_Node`` class itself is rather simple::
|
463 |
|
464 |
-
class Project_Set_Node extends
|
465 |
{
|
466 |
-
public function __construct($name,
|
467 |
{
|
468 |
parent::__construct(['value' => $value], ['name' => $name], $lineno, $tag);
|
469 |
}
|
470 |
|
471 |
-
public function compile(
|
472 |
{
|
473 |
$compiler
|
474 |
->addDebugInfo($this)
|
@@ -492,15 +492,15 @@ developer generate beautiful and readable PHP code:
|
|
492 |
* ``string()``: Writes a quoted string.
|
493 |
|
494 |
* ``repr()``: Writes a PHP representation of a given value (see
|
495 |
-
``
|
496 |
|
497 |
* ``addDebugInfo()``: Adds the line of the original template file related to
|
498 |
the current node as a comment.
|
499 |
|
500 |
-
* ``indent()``: Indents the generated code (see ``
|
501 |
usage example).
|
502 |
|
503 |
-
* ``outdent()``: Outdents the generated code (see ``
|
504 |
usage example).
|
505 |
|
506 |
.. _creating_extensions:
|
@@ -540,7 +540,7 @@ An extension is a class that implements the following interface::
|
|
540 |
*
|
541 |
* This is where you can load some file that contains filter functions for instance.
|
542 |
*/
|
543 |
-
function initRuntime(
|
544 |
|
545 |
/**
|
546 |
* Returns the token parser instances to add to the existing list.
|
@@ -552,28 +552,28 @@ An extension is a class that implements the following interface::
|
|
552 |
/**
|
553 |
* Returns the node visitor instances to add to the existing list.
|
554 |
*
|
555 |
-
* @return
|
556 |
*/
|
557 |
function getNodeVisitors();
|
558 |
|
559 |
/**
|
560 |
* Returns a list of filters to add to the existing list.
|
561 |
*
|
562 |
-
* @return
|
563 |
*/
|
564 |
function getFilters();
|
565 |
|
566 |
/**
|
567 |
* Returns a list of tests to add to the existing list.
|
568 |
*
|
569 |
-
* @return
|
570 |
*/
|
571 |
function getTests();
|
572 |
|
573 |
/**
|
574 |
* Returns a list of functions to add to the existing list.
|
575 |
*
|
576 |
-
* @return
|
577 |
*/
|
578 |
function getFunctions();
|
579 |
|
@@ -600,16 +600,16 @@ An extension is a class that implements the following interface::
|
|
600 |
}
|
601 |
|
602 |
To keep your extension class clean and lean, it can inherit from the built-in
|
603 |
-
``
|
604 |
way, you just need to implement the ``getName()`` method as the
|
605 |
-
``
|
606 |
|
607 |
The ``getName()`` method must return a unique identifier for your extension.
|
608 |
|
609 |
Now, with this information in mind, let's create the most basic extension
|
610 |
possible::
|
611 |
|
612 |
-
class Project_Twig_Extension extends
|
613 |
{
|
614 |
public function getName()
|
615 |
{
|
@@ -628,7 +628,7 @@ extensions must be registered explicitly to be available in your templates.
|
|
628 |
You can register an extension by using the ``addExtension()`` method on your
|
629 |
main ``Environment`` object::
|
630 |
|
631 |
-
$twig = new
|
632 |
$twig->addExtension(new Project_Twig_Extension());
|
633 |
|
634 |
Of course, you need to first load the extension file by either using
|
@@ -644,7 +644,7 @@ Globals
|
|
644 |
Global variables can be registered in an extension via the ``getGlobals()``
|
645 |
method::
|
646 |
|
647 |
-
class Project_Twig_Extension extends
|
648 |
{
|
649 |
public function getGlobals()
|
650 |
{
|
@@ -662,7 +662,7 @@ Functions
|
|
662 |
Functions can be registered in an extension via the ``getFunctions()``
|
663 |
method::
|
664 |
|
665 |
-
class Project_Twig_Extension extends
|
666 |
{
|
667 |
public function getFunctions()
|
668 |
{
|
@@ -681,7 +681,7 @@ To add a filter to an extension, you need to override the ``getFilters()``
|
|
681 |
method. This method must return an array of filters to add to the Twig
|
682 |
environment::
|
683 |
|
684 |
-
class Project_Twig_Extension extends
|
685 |
{
|
686 |
public function getFilters()
|
687 |
{
|
@@ -705,7 +705,7 @@ $twig->addFilter('rot13', new Twig_Filter_Function('Project_Twig_Extension::rot1
|
|
705 |
You can also use ``Twig_Filter_Method`` instead of ``Twig_Filter_Function``
|
706 |
when defining a filter to use a method::
|
707 |
|
708 |
-
class Project_Twig_Extension extends
|
709 |
{
|
710 |
public function getFilters()
|
711 |
{
|
@@ -737,7 +737,7 @@ If some default core filters do not suit your needs, you can easily override
|
|
737 |
them by creating your own extension. Just use the same names as the one you
|
738 |
want to override::
|
739 |
|
740 |
-
class MyCoreExtension extends
|
741 |
{
|
742 |
public function getFilters()
|
743 |
{
|
@@ -762,7 +762,7 @@ Here, we override the ``date`` filter with a custom one. Using this extension
|
|
762 |
is as simple as registering the ``MyCoreExtension`` extension by calling the
|
763 |
``addExtension()`` method on the environment instance::
|
764 |
|
765 |
-
$twig = new
|
766 |
$twig->addExtension(new MyCoreExtension());
|
767 |
|
768 |
Tags
|
@@ -772,7 +772,7 @@ Adding a tag in an extension can be done by overriding the
|
|
772 |
``getTokenParsers()`` method. This method must return an array of tags to add
|
773 |
to the Twig environment::
|
774 |
|
775 |
-
class Project_Twig_Extension extends
|
776 |
{
|
777 |
public function getTokenParsers()
|
778 |
{
|
@@ -792,17 +792,17 @@ Operators
|
|
792 |
The ``getOperators()`` methods allows to add new operators. Here is how to add
|
793 |
``!``, ``||``, and ``&&`` operators::
|
794 |
|
795 |
-
class Project_Twig_Extension extends
|
796 |
{
|
797 |
public function getOperators()
|
798 |
{
|
799 |
return [
|
800 |
[
|
801 |
-
'!' => ['precedence' => 50, 'class' => '
|
802 |
),
|
803 |
[
|
804 |
-
'||' => ['precedence' => 10, 'class' => '
|
805 |
-
'&&' => ['precedence' => 15, 'class' => '
|
806 |
],
|
807 |
];
|
808 |
}
|
@@ -815,7 +815,7 @@ Tests
|
|
815 |
|
816 |
The ``getTests()`` methods allows to add new test functions::
|
817 |
|
818 |
-
class Project_Twig_Extension extends
|
819 |
{
|
820 |
public function getTests()
|
821 |
{
|
@@ -853,7 +853,7 @@ following file structure in your test directory::
|
|
853 |
|
854 |
The ``IntegrationTest.php`` file should look like this::
|
855 |
|
856 |
-
class Project_Tests_IntegrationTest extends
|
857 |
{
|
858 |
public function getExtensions()
|
859 |
{
|
@@ -876,7 +876,7 @@ Node Tests
|
|
876 |
~~~~~~~~~~
|
877 |
|
878 |
Testing the node visitors can be complex, so extend your test cases from
|
879 |
-
|
880 |
`tests/Twig/Node`_ directory.
|
881 |
|
882 |
.. _`spl_autoload_register()`: https://secure.php.net/spl_autoload_register
|
115 |
A global variable is like any other template variable, except that it's
|
116 |
available in all templates and macros::
|
117 |
|
118 |
+
$twig = new \Twig\Environment($loader);
|
119 |
$twig->addGlobal('text', new Text());
|
120 |
|
121 |
You can then use the ``text`` variable anywhere in a template:
|
176 |
{# should displays Gjvt #}
|
177 |
|
178 |
Adding a filter is as simple as calling the ``addFilter()`` method on the
|
179 |
+
``\Twig\Environment`` instance::
|
180 |
|
181 |
+
$twig = new \Twig\Environment($loader);
|
182 |
$twig->addFilter('rot13', new Twig_Filter_Function('str_rot13'));
|
183 |
|
184 |
The second argument of ``addFilter()`` is an instance of ``Twig_Filter``.
|
232 |
Twig will then pass the current environment as the first argument to the
|
233 |
filter call::
|
234 |
|
235 |
+
function twig_compute_rot13(\Twig\Environment $env, $string)
|
236 |
{
|
237 |
// get the current charset for instance
|
238 |
$charset = $env->getCharset();
|
311 |
<?php echo constant('DATE_W3C') ?>
|
312 |
|
313 |
Adding a function is similar to adding a filter. This can be done by calling the
|
314 |
+
``addFunction()`` method on the ``\Twig\Environment`` instance::
|
315 |
|
316 |
+
$twig = new \Twig\Environment($loader);
|
317 |
$twig->addFunction('functionName', new Twig_Function_Function('someFunction'));
|
318 |
|
319 |
You can also expose extension methods as functions in your templates::
|
320 |
|
321 |
+
// $this is an object that implements \Twig\Extension\ExtensionInterface.
|
322 |
+
$twig = new \Twig\Environment($loader);
|
323 |
$twig->addFunction('otherFunction', new Twig_Function_Method($this, 'someMethod'));
|
324 |
|
325 |
Functions also support ``needs_environment`` and ``is_safe`` parameters.
|
395 |
~~~~~~~~~~~~~~~~~~~~~
|
396 |
|
397 |
Adding a tag is as simple as calling the ``addTokenParser`` method on the
|
398 |
+
``\Twig\Environment`` instance::
|
399 |
|
400 |
+
$twig = new \Twig\Environment($loader);
|
401 |
$twig->addTokenParser(new Project_Set_TokenParser());
|
402 |
|
403 |
Defining a Token Parser
|
405 |
|
406 |
Now, let's see the actual code of this class::
|
407 |
|
408 |
+
class Project_Set_TokenParser extends \Twig\TokenParser\AbstractTokenParser
|
409 |
{
|
410 |
+
public function parse(\Twig\Token $token)
|
411 |
{
|
412 |
$lineno = $token->getLine();
|
413 |
+
$name = $this->parser->getStream()->expect(\Twig\Token::NAME_TYPE)->getValue();
|
414 |
+
$this->parser->getStream()->expect(\Twig\Token::OPERATOR_TYPE, '=');
|
415 |
$value = $this->parser->getExpressionParser()->parseExpression();
|
416 |
|
417 |
+
$this->parser->getStream()->expect(\Twig\Token::BLOCK_END_TYPE);
|
418 |
|
419 |
return new Project_Set_Node($name, $value, $lineno, $this->getTag());
|
420 |
}
|
428 |
The ``getTag()`` method must return the tag we want to parse, here ``set``.
|
429 |
|
430 |
The ``parse()`` method is invoked whenever the parser encounters a ``set``
|
431 |
+
tag. It should return a ``\Twig\Node\Node`` instance that represents the node (the
|
432 |
``Project_Set_Node`` calls creating is explained in the next section).
|
433 |
|
434 |
The parsing process is simplified thanks to a bunch of methods you can call
|
461 |
|
462 |
The ``Project_Set_Node`` class itself is rather simple::
|
463 |
|
464 |
+
class Project_Set_Node extends \Twig\Node\Node
|
465 |
{
|
466 |
+
public function __construct($name, \Twig\Node\Expression\AbstractExpression $value, $lineno, $tag = null)
|
467 |
{
|
468 |
parent::__construct(['value' => $value], ['name' => $name], $lineno, $tag);
|
469 |
}
|
470 |
|
471 |
+
public function compile(\Twig\Compiler $compiler)
|
472 |
{
|
473 |
$compiler
|
474 |
->addDebugInfo($this)
|
492 |
* ``string()``: Writes a quoted string.
|
493 |
|
494 |
* ``repr()``: Writes a PHP representation of a given value (see
|
495 |
+
``\Twig\Node\ForNode`` for a usage example).
|
496 |
|
497 |
* ``addDebugInfo()``: Adds the line of the original template file related to
|
498 |
the current node as a comment.
|
499 |
|
500 |
+
* ``indent()``: Indents the generated code (see ``\Twig\Node\BlockNode`` for a
|
501 |
usage example).
|
502 |
|
503 |
+
* ``outdent()``: Outdents the generated code (see ``\Twig\Node\BlockNode`` for a
|
504 |
usage example).
|
505 |
|
506 |
.. _creating_extensions:
|
540 |
*
|
541 |
* This is where you can load some file that contains filter functions for instance.
|
542 |
*/
|
543 |
+
function initRuntime(\Twig\Environment $environment);
|
544 |
|
545 |
/**
|
546 |
* Returns the token parser instances to add to the existing list.
|
552 |
/**
|
553 |
* Returns the node visitor instances to add to the existing list.
|
554 |
*
|
555 |
+
* @return \Twig\NodeVisitor\NodeVisitorInterface[]
|
556 |
*/
|
557 |
function getNodeVisitors();
|
558 |
|
559 |
/**
|
560 |
* Returns a list of filters to add to the existing list.
|
561 |
*
|
562 |
+
* @return \Twig\TwigFilter[]
|
563 |
*/
|
564 |
function getFilters();
|
565 |
|
566 |
/**
|
567 |
* Returns a list of tests to add to the existing list.
|
568 |
*
|
569 |
+
* @return \Twig\TwigTest[]
|
570 |
*/
|
571 |
function getTests();
|
572 |
|
573 |
/**
|
574 |
* Returns a list of functions to add to the existing list.
|
575 |
*
|
576 |
+
* @return \Twig\TwigFunction[]
|
577 |
*/
|
578 |
function getFunctions();
|
579 |
|
600 |
}
|
601 |
|
602 |
To keep your extension class clean and lean, it can inherit from the built-in
|
603 |
+
``\Twig\Extension\AbstractExtension`` class instead of implementing the whole interface. That
|
604 |
way, you just need to implement the ``getName()`` method as the
|
605 |
+
``\Twig\Extension\AbstractExtension`` provides empty implementations for all other methods.
|
606 |
|
607 |
The ``getName()`` method must return a unique identifier for your extension.
|
608 |
|
609 |
Now, with this information in mind, let's create the most basic extension
|
610 |
possible::
|
611 |
|
612 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
613 |
{
|
614 |
public function getName()
|
615 |
{
|
628 |
You can register an extension by using the ``addExtension()`` method on your
|
629 |
main ``Environment`` object::
|
630 |
|
631 |
+
$twig = new \Twig\Environment($loader);
|
632 |
$twig->addExtension(new Project_Twig_Extension());
|
633 |
|
634 |
Of course, you need to first load the extension file by either using
|
644 |
Global variables can be registered in an extension via the ``getGlobals()``
|
645 |
method::
|
646 |
|
647 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
648 |
{
|
649 |
public function getGlobals()
|
650 |
{
|
662 |
Functions can be registered in an extension via the ``getFunctions()``
|
663 |
method::
|
664 |
|
665 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
666 |
{
|
667 |
public function getFunctions()
|
668 |
{
|
681 |
method. This method must return an array of filters to add to the Twig
|
682 |
environment::
|
683 |
|
684 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
685 |
{
|
686 |
public function getFilters()
|
687 |
{
|
705 |
You can also use ``Twig_Filter_Method`` instead of ``Twig_Filter_Function``
|
706 |
when defining a filter to use a method::
|
707 |
|
708 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
709 |
{
|
710 |
public function getFilters()
|
711 |
{
|
737 |
them by creating your own extension. Just use the same names as the one you
|
738 |
want to override::
|
739 |
|
740 |
+
class MyCoreExtension extends \Twig\Extension\AbstractExtension
|
741 |
{
|
742 |
public function getFilters()
|
743 |
{
|
762 |
is as simple as registering the ``MyCoreExtension`` extension by calling the
|
763 |
``addExtension()`` method on the environment instance::
|
764 |
|
765 |
+
$twig = new \Twig\Environment($loader);
|
766 |
$twig->addExtension(new MyCoreExtension());
|
767 |
|
768 |
Tags
|
772 |
``getTokenParsers()`` method. This method must return an array of tags to add
|
773 |
to the Twig environment::
|
774 |
|
775 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
776 |
{
|
777 |
public function getTokenParsers()
|
778 |
{
|
792 |
The ``getOperators()`` methods allows to add new operators. Here is how to add
|
793 |
``!``, ``||``, and ``&&`` operators::
|
794 |
|
795 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
796 |
{
|
797 |
public function getOperators()
|
798 |
{
|
799 |
return [
|
800 |
[
|
801 |
+
'!' => ['precedence' => 50, 'class' => '\Twig\Node\Expression\Unary\NotUnary'],
|
802 |
),
|
803 |
[
|
804 |
+
'||' => ['precedence' => 10, 'class' => '\Twig\Node\Expression\Binary\OrBinary', 'associativity' => \Twig\ExpressionParser::OPERATOR_LEFT],
|
805 |
+
'&&' => ['precedence' => 15, 'class' => '\Twig\Node\Expression\Binary\AndBinary', 'associativity' => \Twig\ExpressionParser::OPERATOR_LEFT],
|
806 |
],
|
807 |
];
|
808 |
}
|
815 |
|
816 |
The ``getTests()`` methods allows to add new test functions::
|
817 |
|
818 |
+
class Project_Twig_Extension extends \Twig\Extension\AbstractExtension
|
819 |
{
|
820 |
public function getTests()
|
821 |
{
|
853 |
|
854 |
The ``IntegrationTest.php`` file should look like this::
|
855 |
|
856 |
+
class Project_Tests_IntegrationTest extends \Twig\Test\IntegrationTestCase
|
857 |
{
|
858 |
public function getExtensions()
|
859 |
{
|
876 |
~~~~~~~~~~
|
877 |
|
878 |
Testing the node visitors can be complex, so extend your test cases from
|
879 |
+
``\Twig\Test\NodeTestCase``. Examples can be found in the Twig repository
|
880 |
`tests/Twig/Node`_ directory.
|
881 |
|
882 |
.. _`spl_autoload_register()`: https://secure.php.net/spl_autoload_register
|
vendor/twig/twig/doc/api.rst
CHANGED
@@ -9,11 +9,11 @@ Basics
|
|
9 |
------
|
10 |
|
11 |
Twig uses a central object called the **environment** (of class
|
12 |
-
``
|
13 |
configuration and extensions, and are used to load templates from the file
|
14 |
system or other locations.
|
15 |
|
16 |
-
Most applications will create one ``
|
17 |
initialization and use that to load templates. In some cases it's however
|
18 |
useful to have multiple environments side by side, if different configurations
|
19 |
are in use.
|
@@ -24,8 +24,8 @@ looks roughly like this::
|
|
24 |
require_once '/path/to/lib/Twig/Autoloader.php';
|
25 |
Twig_Autoloader::register();
|
26 |
|
27 |
-
$loader = new
|
28 |
-
$twig = new
|
29 |
'cache' => '/path/to/compilation_cache',
|
30 |
]);
|
31 |
|
@@ -47,14 +47,14 @@ Rendering Templates
|
|
47 |
-------------------
|
48 |
|
49 |
To load a template from a Twig environment, call the ``load()`` method which
|
50 |
-
returns a ``
|
51 |
|
52 |
$template = $twig->load('index.html');
|
53 |
|
54 |
.. note::
|
55 |
|
56 |
Before Twig 1.28, you should use ``loadTemplate()`` instead which returns a
|
57 |
-
``
|
58 |
|
59 |
To render the template with some variables, call the ``render()`` method::
|
60 |
|
@@ -81,10 +81,10 @@ If a template defines blocks, they can be rendered individually via the
|
|
81 |
Environment Options
|
82 |
-------------------
|
83 |
|
84 |
-
When creating a new ``
|
85 |
options as the constructor second argument::
|
86 |
|
87 |
-
$twig = new
|
88 |
|
89 |
The following options are available:
|
90 |
|
@@ -98,7 +98,7 @@ The following options are available:
|
|
98 |
|
99 |
The charset used by the templates.
|
100 |
|
101 |
-
* ``base_template_class`` *string* (defaults to ``
|
102 |
|
103 |
The base template class to use for generated
|
104 |
templates.
|
@@ -158,7 +158,7 @@ Compilation Cache
|
|
158 |
All template loaders can cache the compiled templates on the filesystem for
|
159 |
future reuse. It speeds up Twig a lot as templates are only compiled once; and
|
160 |
the performance boost is even larger if you use a PHP accelerator such as APC.
|
161 |
-
See the ``cache`` and ``auto_reload`` options of ``
|
162 |
for more information.
|
163 |
|
164 |
Built-in Loaders
|
@@ -166,7 +166,7 @@ Built-in Loaders
|
|
166 |
|
167 |
Here is a list of the built-in loaders Twig provides:
|
168 |
|
169 |
-
``
|
170 |
..........................
|
171 |
|
172 |
.. versionadded:: 1.10
|
@@ -175,15 +175,15 @@ Here is a list of the built-in loaders Twig provides:
|
|
175 |
.. versionadded:: 1.27
|
176 |
Relative paths support was added in Twig 1.27.
|
177 |
|
178 |
-
``
|
179 |
can find templates in folders on the file system and is the preferred way to
|
180 |
load them::
|
181 |
|
182 |
-
$loader = new
|
183 |
|
184 |
It can also look for templates in an array of directories::
|
185 |
|
186 |
-
$loader = new
|
187 |
|
188 |
With such a configuration, Twig will first look for templates in
|
189 |
``$templateDir1`` and if they do not exist, it will fallback to look for them
|
@@ -209,28 +209,28 @@ Namespaced templates can be accessed via the special
|
|
209 |
|
210 |
$twig->render('@admin/index.html', []);
|
211 |
|
212 |
-
``
|
213 |
paths is preferred as it makes the cache keys independent of the project root
|
214 |
directory (for instance, it allows warming the cache from a build server where
|
215 |
the directory might be different from the one used on production servers)::
|
216 |
|
217 |
-
$loader = new
|
218 |
|
219 |
.. note::
|
220 |
|
221 |
When not passing the root path as a second argument, Twig uses ``getcwd()``
|
222 |
for relative paths.
|
223 |
|
224 |
-
``
|
225 |
.....................
|
226 |
|
227 |
-
``
|
228 |
of strings bound to template names::
|
229 |
|
230 |
-
$loader = new
|
231 |
'index.html' => 'Hello {{ name }}!',
|
232 |
]);
|
233 |
-
$twig = new
|
234 |
|
235 |
echo $twig->render('index.html', ['name' => 'Fabien']);
|
236 |
|
@@ -245,30 +245,30 @@ projects where storing all templates in a single PHP file might make sense.
|
|
245 |
don't want to see your cache grows out of control, you need to take care
|
246 |
of clearing the old cache file by yourself.
|
247 |
|
248 |
-
``
|
249 |
.....................
|
250 |
|
251 |
-
``
|
252 |
|
253 |
-
$loader1 = new
|
254 |
'base.html' => '{% block content %}{% endblock %}',
|
255 |
]);
|
256 |
-
$loader2 = new
|
257 |
'index.html' => '{% extends "base.html" %}{% block content %}Hello {{ name }}{% endblock %}',
|
258 |
'base.html' => 'Will never be loaded',
|
259 |
]);
|
260 |
|
261 |
-
$loader = new
|
262 |
|
263 |
-
$twig = new
|
264 |
|
265 |
When looking for a template, Twig will try each loader in turn and it will
|
266 |
return as soon as the template is found. When rendering the ``index.html``
|
267 |
template from the above example, Twig will load it with ``$loader2`` but the
|
268 |
``base.html`` template will be loaded from ``$loader1``.
|
269 |
|
270 |
-
``
|
271 |
-
|
272 |
|
273 |
.. note::
|
274 |
|
@@ -277,7 +277,7 @@ template from the above example, Twig will load it with ``$loader2`` but the
|
|
277 |
Create your own Loader
|
278 |
~~~~~~~~~~~~~~~~~~~~~~
|
279 |
|
280 |
-
All loaders implement the
|
281 |
|
282 |
interface Twig_LoaderInterface
|
283 |
{
|
@@ -288,7 +288,7 @@ All loaders implement the ``Twig_LoaderInterface``::
|
|
288 |
*
|
289 |
* @return string The template source code
|
290 |
*
|
291 |
-
* @deprecated since 1.27 (to be removed in 2.0), implement
|
292 |
*/
|
293 |
function getSource($name);
|
294 |
|
@@ -316,11 +316,11 @@ is still fresh, given the last modification time, or ``false`` otherwise.
|
|
316 |
.. note::
|
317 |
|
318 |
As of Twig 1.27, you should also implement
|
319 |
-
``
|
320 |
|
321 |
.. tip::
|
322 |
|
323 |
-
As of Twig 1.11.0, you can also implement ``
|
324 |
to make your loader faster when used with the chain loader.
|
325 |
|
326 |
Using Extensions
|
@@ -329,7 +329,7 @@ Using Extensions
|
|
329 |
Twig extensions are packages that add new features to Twig. Using an
|
330 |
extension is as simple as using the ``addExtension()`` method::
|
331 |
|
332 |
-
$twig->addExtension(new
|
333 |
|
334 |
Twig comes bundled with the following extensions:
|
335 |
|
@@ -378,7 +378,7 @@ tag, ``autoescape``, and a filter, ``raw``.
|
|
378 |
When creating the escaper extension, you can switch on or off the global
|
379 |
output escaping strategy::
|
380 |
|
381 |
-
$escaper = new
|
382 |
$twig->addExtension($escaper);
|
383 |
|
384 |
If set to ``html``, all variables in templates are escaped (using the ``html``
|
@@ -473,7 +473,7 @@ Sandbox Extension
|
|
473 |
The ``sandbox`` extension can be used to evaluate untrusted code. Access to
|
474 |
unsafe attributes and methods is prohibited. The sandbox security is managed
|
475 |
by a policy instance. By default, Twig comes with one policy class:
|
476 |
-
|
477 |
tags, filters, properties, and methods::
|
478 |
|
479 |
$tags = ['if'];
|
@@ -485,17 +485,17 @@ tags, filters, properties, and methods::
|
|
485 |
'Article' => ['title', 'body'],
|
486 |
];
|
487 |
$functions = ['range'];
|
488 |
-
$policy = new
|
489 |
|
490 |
With the previous configuration, the security policy will only allow usage of
|
491 |
the ``if`` tag, and the ``upper`` filter. Moreover, the templates will only be
|
492 |
able to call the ``getTitle()`` and ``getBody()`` methods on ``Article``
|
493 |
objects, and the ``title`` and ``body`` public properties. Everything else
|
494 |
-
won't be allowed and will generate a ``
|
495 |
|
496 |
The policy object is the first argument of the sandbox constructor::
|
497 |
|
498 |
-
$sandbox = new
|
499 |
$twig->addExtension($sandbox);
|
500 |
|
501 |
By default, the sandbox mode is disabled and should be enabled when including
|
@@ -510,7 +510,7 @@ untrusted template code by using the ``sandbox`` tag:
|
|
510 |
You can sandbox all templates by passing ``true`` as the second argument of
|
511 |
the extension constructor::
|
512 |
|
513 |
-
$sandbox = new
|
514 |
|
515 |
Profiler Extension
|
516 |
~~~~~~~~~~~~~~~~~~
|
@@ -521,10 +521,10 @@ Profiler Extension
|
|
521 |
The ``profiler`` extension enables a profiler for Twig templates; it should
|
522 |
only be used on your development machines as it adds some overhead::
|
523 |
|
524 |
-
$profile = new
|
525 |
-
$twig->addExtension(new
|
526 |
|
527 |
-
$dumper = new
|
528 |
echo $dumper->dump($profile);
|
529 |
|
530 |
A profile contains information about time and memory consumption for template,
|
@@ -533,7 +533,7 @@ block, and macro executions.
|
|
533 |
You can also dump the data in a `Blackfire.io <https://blackfire.io/>`_
|
534 |
compatible format::
|
535 |
|
536 |
-
$dumper = new
|
537 |
file_put_contents('/path/to/profile.prof', $dumper->dump($profile));
|
538 |
|
539 |
Upload the profile to visualize it (create a `free account
|
@@ -548,27 +548,27 @@ Optimizer Extension
|
|
548 |
|
549 |
The ``optimizer`` extension optimizes the node tree before compilation::
|
550 |
|
551 |
-
$twig->addExtension(new
|
552 |
|
553 |
By default, all optimizations are turned on. You can select the ones you want
|
554 |
to enable by passing them to the constructor::
|
555 |
|
556 |
-
$optimizer = new
|
557 |
|
558 |
$twig->addExtension($optimizer);
|
559 |
|
560 |
Twig supports the following optimizations:
|
561 |
|
562 |
-
*
|
563 |
(this is the default value).
|
564 |
-
*
|
565 |
This reduces the compilation time, but it can increase the execution time
|
566 |
and the consumed memory.
|
567 |
-
*
|
568 |
removing the ``loop`` variable creation whenever possible.
|
569 |
-
*
|
570 |
filter whenever possible.
|
571 |
-
*
|
572 |
and access of variables in the compiled templates whenever possible.
|
573 |
|
574 |
Exceptions
|
@@ -576,15 +576,15 @@ Exceptions
|
|
576 |
|
577 |
Twig can throw exceptions:
|
578 |
|
579 |
-
*
|
580 |
|
581 |
-
*
|
582 |
the template syntax.
|
583 |
|
584 |
-
*
|
585 |
does not exist for instance).
|
586 |
|
587 |
-
*
|
588 |
|
589 |
-
*
|
590 |
method is called in a sandboxed template.
|
9 |
------
|
10 |
|
11 |
Twig uses a central object called the **environment** (of class
|
12 |
+
``\Twig\Environment``). Instances of this class are used to store the
|
13 |
configuration and extensions, and are used to load templates from the file
|
14 |
system or other locations.
|
15 |
|
16 |
+
Most applications will create one ``\Twig\Environment`` object on application
|
17 |
initialization and use that to load templates. In some cases it's however
|
18 |
useful to have multiple environments side by side, if different configurations
|
19 |
are in use.
|
24 |
require_once '/path/to/lib/Twig/Autoloader.php';
|
25 |
Twig_Autoloader::register();
|
26 |
|
27 |
+
$loader = new \Twig\Loader\FilesystemLoader('/path/to/templates');
|
28 |
+
$twig = new \Twig\Environment($loader, [
|
29 |
'cache' => '/path/to/compilation_cache',
|
30 |
]);
|
31 |
|
47 |
-------------------
|
48 |
|
49 |
To load a template from a Twig environment, call the ``load()`` method which
|
50 |
+
returns a ``\Twig\TemplateWrapper`` instance::
|
51 |
|
52 |
$template = $twig->load('index.html');
|
53 |
|
54 |
.. note::
|
55 |
|
56 |
Before Twig 1.28, you should use ``loadTemplate()`` instead which returns a
|
57 |
+
``\Twig\Template`` instance.
|
58 |
|
59 |
To render the template with some variables, call the ``render()`` method::
|
60 |
|
81 |
Environment Options
|
82 |
-------------------
|
83 |
|
84 |
+
When creating a new ``\Twig\Environment`` instance, you can pass an array of
|
85 |
options as the constructor second argument::
|
86 |
|
87 |
+
$twig = new \Twig\Environment($loader, ['debug' => true]);
|
88 |
|
89 |
The following options are available:
|
90 |
|
98 |
|
99 |
The charset used by the templates.
|
100 |
|
101 |
+
* ``base_template_class`` *string* (defaults to ``\Twig\Template``)
|
102 |
|
103 |
The base template class to use for generated
|
104 |
templates.
|
158 |
All template loaders can cache the compiled templates on the filesystem for
|
159 |
future reuse. It speeds up Twig a lot as templates are only compiled once; and
|
160 |
the performance boost is even larger if you use a PHP accelerator such as APC.
|
161 |
+
See the ``cache`` and ``auto_reload`` options of ``\Twig\Environment`` above
|
162 |
for more information.
|
163 |
|
164 |
Built-in Loaders
|
166 |
|
167 |
Here is a list of the built-in loaders Twig provides:
|
168 |
|
169 |
+
``\Twig\Loader\FilesystemLoader``
|
170 |
..........................
|
171 |
|
172 |
.. versionadded:: 1.10
|
175 |
.. versionadded:: 1.27
|
176 |
Relative paths support was added in Twig 1.27.
|
177 |
|
178 |
+
``\Twig\Loader\FilesystemLoader`` loads templates from the file system. This loader
|
179 |
can find templates in folders on the file system and is the preferred way to
|
180 |
load them::
|
181 |
|
182 |
+
$loader = new \Twig\Loader\FilesystemLoader($templateDir);
|
183 |
|
184 |
It can also look for templates in an array of directories::
|
185 |
|
186 |
+
$loader = new \Twig\Loader\FilesystemLoader([$templateDir1, $templateDir2]);
|
187 |
|
188 |
With such a configuration, Twig will first look for templates in
|
189 |
``$templateDir1`` and if they do not exist, it will fallback to look for them
|
209 |
|
210 |
$twig->render('@admin/index.html', []);
|
211 |
|
212 |
+
``\Twig\Loader\FilesystemLoader`` support absolute and relative paths. Using relative
|
213 |
paths is preferred as it makes the cache keys independent of the project root
|
214 |
directory (for instance, it allows warming the cache from a build server where
|
215 |
the directory might be different from the one used on production servers)::
|
216 |
|
217 |
+
$loader = new \Twig\Loader\FilesystemLoader('templates', getcwd().'/..');
|
218 |
|
219 |
.. note::
|
220 |
|
221 |
When not passing the root path as a second argument, Twig uses ``getcwd()``
|
222 |
for relative paths.
|
223 |
|
224 |
+
``\Twig\Loader\ArrayLoader``
|
225 |
.....................
|
226 |
|
227 |
+
``\Twig\Loader\ArrayLoader`` loads a template from a PHP array. It's passed an array
|
228 |
of strings bound to template names::
|
229 |
|
230 |
+
$loader = new \Twig\Loader\ArrayLoader([
|
231 |
'index.html' => 'Hello {{ name }}!',
|
232 |
]);
|
233 |
+
$twig = new \Twig\Environment($loader);
|
234 |
|
235 |
echo $twig->render('index.html', ['name' => 'Fabien']);
|
236 |
|
245 |
don't want to see your cache grows out of control, you need to take care
|
246 |
of clearing the old cache file by yourself.
|
247 |
|
248 |
+
``\Twig\Loader\ChainLoader``
|
249 |
.....................
|
250 |
|
251 |
+
``\Twig\Loader\ChainLoader`` delegates the loading of templates to other loaders::
|
252 |
|
253 |
+
$loader1 = new \Twig\Loader\ArrayLoader([
|
254 |
'base.html' => '{% block content %}{% endblock %}',
|
255 |
]);
|
256 |
+
$loader2 = new \Twig\Loader\ArrayLoader([
|
257 |
'index.html' => '{% extends "base.html" %}{% block content %}Hello {{ name }}{% endblock %}',
|
258 |
'base.html' => 'Will never be loaded',
|
259 |
]);
|
260 |
|
261 |
+
$loader = new \Twig\Loader\ChainLoader([$loader1, $loader2]);
|
262 |
|
263 |
+
$twig = new \Twig\Environment($loader);
|
264 |
|
265 |
When looking for a template, Twig will try each loader in turn and it will
|
266 |
return as soon as the template is found. When rendering the ``index.html``
|
267 |
template from the above example, Twig will load it with ``$loader2`` but the
|
268 |
``base.html`` template will be loaded from ``$loader1``.
|
269 |
|
270 |
+
``\Twig\Loader\ChainLoader`` accepts any loader that implements
|
271 |
+
``\Twig\Loader\LoaderInterface``.
|
272 |
|
273 |
.. note::
|
274 |
|
277 |
Create your own Loader
|
278 |
~~~~~~~~~~~~~~~~~~~~~~
|
279 |
|
280 |
+
All loaders implement the ``\Twig\Loader\LoaderInterface``::
|
281 |
|
282 |
interface Twig_LoaderInterface
|
283 |
{
|
288 |
*
|
289 |
* @return string The template source code
|
290 |
*
|
291 |
+
* @deprecated since 1.27 (to be removed in 2.0), implement \Twig\Loader\SourceContextLoaderInterface
|
292 |
*/
|
293 |
function getSource($name);
|
294 |
|
316 |
.. note::
|
317 |
|
318 |
As of Twig 1.27, you should also implement
|
319 |
+
``\Twig\Loader\SourceContextLoaderInterface`` to avoid deprecation notices.
|
320 |
|
321 |
.. tip::
|
322 |
|
323 |
+
As of Twig 1.11.0, you can also implement ``\Twig\Loader\ExistsLoaderInterface``
|
324 |
to make your loader faster when used with the chain loader.
|
325 |
|
326 |
Using Extensions
|
329 |
Twig extensions are packages that add new features to Twig. Using an
|
330 |
extension is as simple as using the ``addExtension()`` method::
|
331 |
|
332 |
+
$twig->addExtension(new \Twig\Extension\SandboxExtension());
|
333 |
|
334 |
Twig comes bundled with the following extensions:
|
335 |
|
378 |
When creating the escaper extension, you can switch on or off the global
|
379 |
output escaping strategy::
|
380 |
|
381 |
+
$escaper = new \Twig\Extension\EscaperExtension('html');
|
382 |
$twig->addExtension($escaper);
|
383 |
|
384 |
If set to ``html``, all variables in templates are escaped (using the ``html``
|
473 |
The ``sandbox`` extension can be used to evaluate untrusted code. Access to
|
474 |
unsafe attributes and methods is prohibited. The sandbox security is managed
|
475 |
by a policy instance. By default, Twig comes with one policy class:
|
476 |
+
``\Twig\Sandbox\SecurityPolicy``. This class allows you to white-list some
|
477 |
tags, filters, properties, and methods::
|
478 |
|
479 |
$tags = ['if'];
|
485 |
'Article' => ['title', 'body'],
|
486 |
];
|
487 |
$functions = ['range'];
|
488 |
+
$policy = new \Twig\Sandbox\SecurityPolicy($tags, $filters, $methods, $properties, $functions);
|
489 |
|
490 |
With the previous configuration, the security policy will only allow usage of
|
491 |
the ``if`` tag, and the ``upper`` filter. Moreover, the templates will only be
|
492 |
able to call the ``getTitle()`` and ``getBody()`` methods on ``Article``
|
493 |
objects, and the ``title`` and ``body`` public properties. Everything else
|
494 |
+
won't be allowed and will generate a ``\Twig\Sandbox\SecurityError`` exception.
|
495 |
|
496 |
The policy object is the first argument of the sandbox constructor::
|
497 |
|
498 |
+
$sandbox = new \Twig\Extension\SandboxExtension($policy);
|
499 |
$twig->addExtension($sandbox);
|
500 |
|
501 |
By default, the sandbox mode is disabled and should be enabled when including
|
510 |
You can sandbox all templates by passing ``true`` as the second argument of
|
511 |
the extension constructor::
|
512 |
|
513 |
+
$sandbox = new \Twig\Extension\SandboxExtension($policy, true);
|
514 |
|
515 |
Profiler Extension
|
516 |
~~~~~~~~~~~~~~~~~~
|
521 |
The ``profiler`` extension enables a profiler for Twig templates; it should
|
522 |
only be used on your development machines as it adds some overhead::
|
523 |
|
524 |
+
$profile = new \Twig\Profiler\Profile();
|
525 |
+
$twig->addExtension(new \Twig\Extension\ProfilerExtension($profile));
|
526 |
|
527 |
+
$dumper = new \Twig\Profiler\Dumper\TextDumper();
|
528 |
echo $dumper->dump($profile);
|
529 |
|
530 |
A profile contains information about time and memory consumption for template,
|
533 |
You can also dump the data in a `Blackfire.io <https://blackfire.io/>`_
|
534 |
compatible format::
|
535 |
|
536 |
+
$dumper = new \Twig\Profiler\Dumper\BlackfireDumper();
|
537 |
file_put_contents('/path/to/profile.prof', $dumper->dump($profile));
|
538 |
|
539 |
Upload the profile to visualize it (create a `free account
|
548 |
|
549 |
The ``optimizer`` extension optimizes the node tree before compilation::
|
550 |
|
551 |
+
$twig->addExtension(new \Twig\Extension\OptimizerExtension());
|
552 |
|
553 |
By default, all optimizations are turned on. You can select the ones you want
|
554 |
to enable by passing them to the constructor::
|
555 |
|
556 |
+
$optimizer = new \Twig\Extension\OptimizerExtension(\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_FOR);
|
557 |
|
558 |
$twig->addExtension($optimizer);
|
559 |
|
560 |
Twig supports the following optimizations:
|
561 |
|
562 |
+
* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_ALL``, enables all optimizations
|
563 |
(this is the default value).
|
564 |
+
* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_NONE``, disables all optimizations.
|
565 |
This reduces the compilation time, but it can increase the execution time
|
566 |
and the consumed memory.
|
567 |
+
* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_FOR``, optimizes the ``for`` tag by
|
568 |
removing the ``loop`` variable creation whenever possible.
|
569 |
+
* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_RAW_FILTER``, removes the ``raw``
|
570 |
filter whenever possible.
|
571 |
+
* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_VAR_ACCESS``, simplifies the creation
|
572 |
and access of variables in the compiled templates whenever possible.
|
573 |
|
574 |
Exceptions
|
576 |
|
577 |
Twig can throw exceptions:
|
578 |
|
579 |
+
* ``\Twig\Error\Error``: The base exception for all errors.
|
580 |
|
581 |
+
* ``\Twig\Error\SyntaxError``: Thrown to tell the user that there is a problem with
|
582 |
the template syntax.
|
583 |
|
584 |
+
* ``\Twig\Error\RuntimeError``: Thrown when an error occurs at runtime (when a filter
|
585 |
does not exist for instance).
|
586 |
|
587 |
+
* ``\Twig\Error\LoaderError``: Thrown when an error occurs during template loading.
|
588 |
|
589 |
+
* ``\Twig\Sandbox\SecurityError``: Thrown when an unallowed tag, filter, or
|
590 |
method is called in a sandboxed template.
|
vendor/twig/twig/doc/deprecated.rst
CHANGED
@@ -27,29 +27,29 @@ Token Parsers
|
|
27 |
* ``Twig_TokenParserBrokerInterface``
|
28 |
* ``Twig_TokenParserBroker``
|
29 |
|
30 |
-
* As of Twig 1.27,
|
31 |
parser, use ``$this->parser->getStream()->getSourceContext()->getPath()`` instead.
|
32 |
|
33 |
-
* As of Twig 1.27,
|
34 |
|
35 |
Extensions
|
36 |
----------
|
37 |
|
38 |
* As of Twig 1.x, the ability to remove an extension is deprecated and the
|
39 |
-
|
40 |
|
41 |
-
* As of Twig 1.23, the
|
42 |
deprecated. You have two options to avoid the deprecation notice: if you
|
43 |
implement this method to store the environment for your custom filters,
|
44 |
functions, or tests, use the ``needs_environment`` option instead; if you
|
45 |
have more complex needs, explicitly implement
|
46 |
-
``
|
47 |
|
48 |
-
* As of Twig 1.23, the
|
49 |
-
deprecated. Implement ``
|
50 |
deprecation notices.
|
51 |
|
52 |
-
* As of Twig 1.26, the
|
53 |
deprecated and it is not used internally anymore.
|
54 |
|
55 |
PEAR
|
@@ -61,7 +61,7 @@ provided anymore. Use Composer instead.
|
|
61 |
Filters
|
62 |
-------
|
63 |
|
64 |
-
* As of Twig 1.x, use ``
|
65 |
classes and interfaces will be removed in 2.0:
|
66 |
|
67 |
* ``Twig_FilterInterface``
|
@@ -71,14 +71,14 @@ Filters
|
|
71 |
* ``Twig_Filter_Method``
|
72 |
* ``Twig_Filter_Node``
|
73 |
|
74 |
-
* As of Twig 2.x, the ``
|
75 |
removed in Twig 3.x (use ``Twig_Filter`` instead). In Twig 2.x,
|
76 |
-
``
|
77 |
|
78 |
Functions
|
79 |
---------
|
80 |
|
81 |
-
* As of Twig 1.x, use ``
|
82 |
classes and interfaces will be removed in 2.0:
|
83 |
|
84 |
* ``Twig_FunctionInterface``
|
@@ -88,14 +88,14 @@ Functions
|
|
88 |
* ``Twig_Function_Method``
|
89 |
* ``Twig_Function_Node``
|
90 |
|
91 |
-
* As of Twig 2.x, the ``
|
92 |
removed in Twig 3.x (use ``Twig_Function`` instead). In Twig 2.x,
|
93 |
-
``
|
94 |
|
95 |
Tests
|
96 |
-----
|
97 |
|
98 |
-
* As of Twig 1.x, use ``
|
99 |
and interfaces will be removed in 2.0:
|
100 |
|
101 |
* ``Twig_TestInterface``
|
@@ -105,9 +105,9 @@ Tests
|
|
105 |
* ``Twig_Test_Method``
|
106 |
* ``Twig_Test_Node``
|
107 |
|
108 |
-
* As of Twig 2.x, the ``
|
109 |
removed in Twig 3.x (use ``Twig_Test`` instead). In Twig 2.x,
|
110 |
-
``
|
111 |
|
112 |
* The ``sameas`` and ``divisibleby`` tests are deprecated in favor of ``same
|
113 |
as`` and ``divisible by`` respectively.
|
@@ -124,16 +124,16 @@ Nodes
|
|
124 |
* As of Twig 1.x, ``Node::toXml()`` is deprecated and will be removed in Twig
|
125 |
2.0.
|
126 |
|
127 |
-
* As of Twig 1.26, ``Node::$nodes`` should only contains ``
|
128 |
instances, storing a ``null`` value is deprecated and won't be possible in
|
129 |
Twig 2.x.
|
130 |
|
131 |
-
* As of Twig 1.27, the ``filename`` attribute on ``
|
132 |
deprecated. Use ``getName()`` instead.
|
133 |
|
134 |
-
* As of Twig 1.27, the
|
135 |
methods are deprecated, use
|
136 |
-
|
137 |
|
138 |
Interfaces
|
139 |
----------
|
@@ -141,40 +141,40 @@ Interfaces
|
|
141 |
* As of Twig 2.x, the following interfaces are deprecated and empty (they will
|
142 |
be removed in Twig 3.0):
|
143 |
|
144 |
-
* ``Twig_CompilerInterface`` (use ``
|
145 |
-
* ``Twig_LexerInterface`` (use ``
|
146 |
-
* ``Twig_NodeInterface`` (use ``
|
147 |
-
* ``Twig_ParserInterface`` (use ``
|
148 |
-
* ``
|
149 |
-
* ``
|
150 |
-
* ``Twig_TemplateInterface`` (use ``
|
151 |
-
those constants
|
152 |
-
|
153 |
|
154 |
Compiler
|
155 |
--------
|
156 |
|
157 |
-
* As of Twig 1.26, the
|
158 |
You should not use it anyway as its values is not reliable.
|
159 |
|
160 |
-
* As of Twig 1.27, the
|
161 |
-
Use
|
162 |
|
163 |
Loaders
|
164 |
-------
|
165 |
|
166 |
* As of Twig 1.x, ``Twig_Loader_String`` is deprecated and will be removed in
|
167 |
-
2.0. You can render a string via
|
168 |
|
169 |
-
* As of Twig 1.27,
|
170 |
-
Implement ``
|
171 |
``getSourceContext()``.
|
172 |
|
173 |
Node Visitors
|
174 |
-------------
|
175 |
|
176 |
* Because of the removal of ``Twig_NodeInterface`` in 2.0, you need to extend
|
177 |
-
``
|
178 |
directly to make your node visitors compatible with both Twig 1.x and 2.x.
|
179 |
|
180 |
Globals
|
@@ -185,40 +185,40 @@ Globals
|
|
185 |
changing the value of an already registered global is possible).
|
186 |
|
187 |
* As of Twig 1.x, using the ``_self`` global variable to get access to the
|
188 |
-
current ``
|
189 |
current template name, which will continue to work in Twig 2.0. In Twig 2.0,
|
190 |
``_self`` returns the current template name instead of the current
|
191 |
-
``
|
192 |
just replace it with ``{{ _self }}``.
|
193 |
|
194 |
Miscellaneous
|
195 |
-------------
|
196 |
|
197 |
-
* As of Twig 1.x,
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
|
205 |
-
* As of Twig 1.x,
|
206 |
``Twig_TemplateInterface::getEnvironment()`` are deprecated and will be
|
207 |
removed in 2.0.
|
208 |
|
209 |
* As of Twig 1.21, setting the environment option ``autoescape`` to ``true`` is
|
210 |
deprecated and will be removed in 2.0. Use ``"html"`` instead.
|
211 |
|
212 |
-
* As of Twig 1.27,
|
213 |
-
|
214 |
-
|
215 |
instead.
|
216 |
|
217 |
-
* As of Twig 1.27,
|
218 |
-
|
219 |
|
220 |
-
* As of Twig 1.27,
|
221 |
-
|
222 |
|
223 |
* As of Twig 1.29, some classes are marked as being final via the `@final`
|
224 |
annotation. Those classes will be marked as final in 2.0.
|
27 |
* ``Twig_TokenParserBrokerInterface``
|
28 |
* ``Twig_TokenParserBroker``
|
29 |
|
30 |
+
* As of Twig 1.27, ``\Twig\Parser::getFilename()`` is deprecated. From a token
|
31 |
parser, use ``$this->parser->getStream()->getSourceContext()->getPath()`` instead.
|
32 |
|
33 |
+
* As of Twig 1.27, ``\Twig\Parser::getEnvironment()`` is deprecated.
|
34 |
|
35 |
Extensions
|
36 |
----------
|
37 |
|
38 |
* As of Twig 1.x, the ability to remove an extension is deprecated and the
|
39 |
+
``\Twig\Environment::removeExtension()`` method will be removed in 2.0.
|
40 |
|
41 |
+
* As of Twig 1.23, the ``\Twig\Extension\ExtensionInterface::initRuntime()`` method is
|
42 |
deprecated. You have two options to avoid the deprecation notice: if you
|
43 |
implement this method to store the environment for your custom filters,
|
44 |
functions, or tests, use the ``needs_environment`` option instead; if you
|
45 |
have more complex needs, explicitly implement
|
46 |
+
``\Twig\Extension\InitRuntimeInterface`` (not recommended).
|
47 |
|
48 |
+
* As of Twig 1.23, the ``\Twig\Extension\ExtensionInterface::getGlobals()`` method is
|
49 |
+
deprecated. Implement ``\Twig\Extension\GlobalsInterface`` to avoid
|
50 |
deprecation notices.
|
51 |
|
52 |
+
* As of Twig 1.26, the ``\Twig\Extension\ExtensionInterface::getName()`` method is
|
53 |
deprecated and it is not used internally anymore.
|
54 |
|
55 |
PEAR
|
61 |
Filters
|
62 |
-------
|
63 |
|
64 |
+
* As of Twig 1.x, use ``\Twig\TwigFilter`` to add a filter. The following
|
65 |
classes and interfaces will be removed in 2.0:
|
66 |
|
67 |
* ``Twig_FilterInterface``
|
71 |
* ``Twig_Filter_Method``
|
72 |
* ``Twig_Filter_Node``
|
73 |
|
74 |
+
* As of Twig 2.x, the ``\Twig\TwigFilter`` class is deprecated and will be
|
75 |
removed in Twig 3.x (use ``Twig_Filter`` instead). In Twig 2.x,
|
76 |
+
``\Twig\TwigFilter`` is just an alias for ``Twig_Filter``.
|
77 |
|
78 |
Functions
|
79 |
---------
|
80 |
|
81 |
+
* As of Twig 1.x, use ``\Twig\TwigFunction`` to add a function. The following
|
82 |
classes and interfaces will be removed in 2.0:
|
83 |
|
84 |
* ``Twig_FunctionInterface``
|
88 |
* ``Twig_Function_Method``
|
89 |
* ``Twig_Function_Node``
|
90 |
|
91 |
+
* As of Twig 2.x, the ``\Twig\TwigFunction`` class is deprecated and will be
|
92 |
removed in Twig 3.x (use ``Twig_Function`` instead). In Twig 2.x,
|
93 |
+
``\Twig\TwigFunction`` is just an alias for ``Twig_Function``.
|
94 |
|
95 |
Tests
|
96 |
-----
|
97 |
|
98 |
+
* As of Twig 1.x, use ``\Twig\TwigTest`` to add a test. The following classes
|
99 |
and interfaces will be removed in 2.0:
|
100 |
|
101 |
* ``Twig_TestInterface``
|
105 |
* ``Twig_Test_Method``
|
106 |
* ``Twig_Test_Node``
|
107 |
|
108 |
+
* As of Twig 2.x, the ``\Twig\TwigTest`` class is deprecated and will be
|
109 |
removed in Twig 3.x (use ``Twig_Test`` instead). In Twig 2.x,
|
110 |
+
``\Twig\TwigTest`` is just an alias for ``Twig_Test``.
|
111 |
|
112 |
* The ``sameas`` and ``divisibleby`` tests are deprecated in favor of ``same
|
113 |
as`` and ``divisible by`` respectively.
|
124 |
* As of Twig 1.x, ``Node::toXml()`` is deprecated and will be removed in Twig
|
125 |
2.0.
|
126 |
|
127 |
+
* As of Twig 1.26, ``Node::$nodes`` should only contains ``\Twig\Node\Node``
|
128 |
instances, storing a ``null`` value is deprecated and won't be possible in
|
129 |
Twig 2.x.
|
130 |
|
131 |
+
* As of Twig 1.27, the ``filename`` attribute on ``\Twig\Node\ModuleNode`` is
|
132 |
deprecated. Use ``getName()`` instead.
|
133 |
|
134 |
+
* As of Twig 1.27, the ``\Twig\Node\Node::getFilename()/\Twig\Node\Node::getLine()``
|
135 |
methods are deprecated, use
|
136 |
+
``\Twig\Node\Node::getTemplateName()/\Twig\Node\Node::getTemplateLine()`` instead.
|
137 |
|
138 |
Interfaces
|
139 |
----------
|
141 |
* As of Twig 2.x, the following interfaces are deprecated and empty (they will
|
142 |
be removed in Twig 3.0):
|
143 |
|
144 |
+
* ``Twig_CompilerInterface`` (use ``\Twig\Compiler`` instead)
|
145 |
+
* ``Twig_LexerInterface`` (use ``\Twig\Lexer`` instead)
|
146 |
+
* ``Twig_NodeInterface`` (use ``\Twig\Node\Node`` instead)
|
147 |
+
* ``Twig_ParserInterface`` (use ``\Twig\Parser`` instead)
|
148 |
+
* ``\Twig\Loader\ExistsLoaderInterface`` (merged with ``\Twig\Loader\LoaderInterface``)
|
149 |
+
* ``\Twig\Loader\SourceContextLoaderInterface`` (merged with ``\Twig\Loader\LoaderInterface``)
|
150 |
+
* ``Twig_TemplateInterface`` (use ``\Twig\Template`` instead, and use
|
151 |
+
those constants \Twig\Template::ANY_CALL, \Twig\Template::ARRAY_CALL,
|
152 |
+
\Twig\Template::METHOD_CALL)
|
153 |
|
154 |
Compiler
|
155 |
--------
|
156 |
|
157 |
+
* As of Twig 1.26, the ``\Twig\Compiler::getFilename()`` has been deprecated.
|
158 |
You should not use it anyway as its values is not reliable.
|
159 |
|
160 |
+
* As of Twig 1.27, the ``\Twig\Compiler::addIndentation()`` has been deprecated.
|
161 |
+
Use ``\Twig\Compiler::write('')`` instead.
|
162 |
|
163 |
Loaders
|
164 |
-------
|
165 |
|
166 |
* As of Twig 1.x, ``Twig_Loader_String`` is deprecated and will be removed in
|
167 |
+
2.0. You can render a string via ``\Twig\Environment::createTemplate()``.
|
168 |
|
169 |
+
* As of Twig 1.27, ``\Twig\Loader\LoaderInterface::getSource()`` is deprecated.
|
170 |
+
Implement ``\Twig\Loader\SourceContextLoaderInterface`` instead and use
|
171 |
``getSourceContext()``.
|
172 |
|
173 |
Node Visitors
|
174 |
-------------
|
175 |
|
176 |
* Because of the removal of ``Twig_NodeInterface`` in 2.0, you need to extend
|
177 |
+
``\Twig\NodeVisitor\AbstractNodeVisitor`` instead of implementing ``\Twig\NodeVisitor\NodeVisitorInterface``
|
178 |
directly to make your node visitors compatible with both Twig 1.x and 2.x.
|
179 |
|
180 |
Globals
|
185 |
changing the value of an already registered global is possible).
|
186 |
|
187 |
* As of Twig 1.x, using the ``_self`` global variable to get access to the
|
188 |
+
current ``\Twig\Template`` instance is deprecated; most usages only need the
|
189 |
current template name, which will continue to work in Twig 2.0. In Twig 2.0,
|
190 |
``_self`` returns the current template name instead of the current
|
191 |
+
``\Twig\Template`` instance. If you are using ``{{ _self.templateName }}``,
|
192 |
just replace it with ``{{ _self }}``.
|
193 |
|
194 |
Miscellaneous
|
195 |
-------------
|
196 |
|
197 |
+
* As of Twig 1.x, ``\Twig\Environment::clearTemplateCache()``,
|
198 |
+
``\Twig\Environment::writeCacheFile()``,
|
199 |
+
``\Twig\Environment::clearCacheFiles()``,
|
200 |
+
``\Twig\Environment::getCacheFilename()``,
|
201 |
+
``\Twig\Environment::getTemplateClassPrefix()``,
|
202 |
+
``\Twig\Environment::getLexer()``, ``\Twig\Environment::getParser()``, and
|
203 |
+
``\Twig\Environment::getCompiler()`` are deprecated and will be removed in 2.0.
|
204 |
|
205 |
+
* As of Twig 1.x, ``\Twig\Template::getEnvironment()`` and
|
206 |
``Twig_TemplateInterface::getEnvironment()`` are deprecated and will be
|
207 |
removed in 2.0.
|
208 |
|
209 |
* As of Twig 1.21, setting the environment option ``autoescape`` to ``true`` is
|
210 |
deprecated and will be removed in 2.0. Use ``"html"`` instead.
|
211 |
|
212 |
+
* As of Twig 1.27, ``\Twig\Error\Error::getTemplateFile()`` and
|
213 |
+
``\Twig\Error\Error::setTemplateFile()`` are deprecated. Use
|
214 |
+
``\Twig\Error\Error::getTemplateName()`` and ``\Twig\Error\Error::setTemplateName()``
|
215 |
instead.
|
216 |
|
217 |
+
* As of Twig 1.27, ``\Twig\Template::getSource()`` is deprecated. Use
|
218 |
+
``\Twig\Template::getSourceContext()`` instead.
|
219 |
|
220 |
+
* As of Twig 1.27, ``\Twig\Parser::addHandler()`` and
|
221 |
+
``\Twig\Parser::addNodeVisitor()`` are deprecated and will be removed in 2.0.
|
222 |
|
223 |
* As of Twig 1.29, some classes are marked as being final via the `@final`
|
224 |
annotation. Those classes will be marked as final in 2.0.
|
vendor/twig/twig/doc/filters/date.rst
CHANGED
@@ -53,8 +53,8 @@ dates and the second one is the default format for date intervals:
|
|
53 |
|
54 |
.. code-block:: php
|
55 |
|
56 |
-
$twig = new
|
57 |
-
$twig->getExtension('
|
58 |
|
59 |
// before Twig 1.26
|
60 |
$twig->getExtension('core')->setDateFormat('d/m/Y', '%d days');
|
@@ -81,8 +81,8 @@ The default timezone can also be set globally by calling ``setTimezone()``:
|
|
81 |
|
82 |
.. code-block:: php
|
83 |
|
84 |
-
$twig = new
|
85 |
-
$twig->getExtension('
|
86 |
|
87 |
// before Twig 1.26
|
88 |
$twig->getExtension('core')->setTimezone('Europe/Paris');
|
53 |
|
54 |
.. code-block:: php
|
55 |
|
56 |
+
$twig = new \Twig\Environment($loader);
|
57 |
+
$twig->getExtension('\Twig\Extension\CoreExtension')->setDateFormat('d/m/Y', '%d days');
|
58 |
|
59 |
// before Twig 1.26
|
60 |
$twig->getExtension('core')->setDateFormat('d/m/Y', '%d days');
|
81 |
|
82 |
.. code-block:: php
|
83 |
|
84 |
+
$twig = new \Twig\Environment($loader);
|
85 |
+
$twig->getExtension('\Twig\Extension\CoreExtension')->setTimezone('Europe/Paris');
|
86 |
|
87 |
// before Twig 1.26
|
88 |
$twig->getExtension('core')->setTimezone('Europe/Paris');
|
vendor/twig/twig/doc/filters/escape.rst
CHANGED
@@ -96,8 +96,8 @@ used in the ``escape`` call) and the second one must be a valid PHP callable:
|
|
96 |
|
97 |
.. code-block:: php
|
98 |
|
99 |
-
$twig = new
|
100 |
-
$twig->getExtension('
|
101 |
|
102 |
// before Twig 1.26
|
103 |
$twig->getExtension('core')->setEscaper('csv', 'csv_escaper');
|
96 |
|
97 |
.. code-block:: php
|
98 |
|
99 |
+
$twig = new \Twig\Environment($loader);
|
100 |
+
$twig->getExtension('\Twig\Extension\CoreExtension')->setEscaper('csv', 'csv_escaper');
|
101 |
|
102 |
// before Twig 1.26
|
103 |
$twig->getExtension('core')->setEscaper('csv', 'csv_escaper');
|
vendor/twig/twig/doc/filters/join.rst
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
``join``
|
2 |
========
|
3 |
|
4 |
-
.. versionadded:: 1.
|
5 |
-
The ``and`` argument was added in Twig 1.
|
6 |
|
7 |
The ``join`` filter returns a string which is the concatenation of the items
|
8 |
of a sequence:
|
1 |
``join``
|
2 |
========
|
3 |
|
4 |
+
.. versionadded:: 1.37 and 2.6.1
|
5 |
+
The ``and`` argument was added in Twig 1.37 and 2.6.1.
|
6 |
|
7 |
The ``join`` filter returns a string which is the concatenation of the items
|
8 |
of a sequence:
|
vendor/twig/twig/doc/filters/number_format.rst
CHANGED
@@ -37,8 +37,8 @@ These defaults can be easily changed through the core extension:
|
|
37 |
|
38 |
.. code-block:: php
|
39 |
|
40 |
-
$twig = new
|
41 |
-
$twig->getExtension('
|
42 |
|
43 |
// before Twig 1.26
|
44 |
$twig->getExtension('core')->setNumberFormat(3, '.', ',');
|
37 |
|
38 |
.. code-block:: php
|
39 |
|
40 |
+
$twig = new \Twig\Environment($loader);
|
41 |
+
$twig->getExtension('\Twig\Extension\CoreExtension')->setNumberFormat(3, '.', ',');
|
42 |
|
43 |
// before Twig 1.26
|
44 |
$twig->getExtension('core')->setNumberFormat(3, '.', ',');
|
vendor/twig/twig/doc/functions/date.rst
CHANGED
@@ -40,8 +40,8 @@ If no argument is passed, the function returns the current date:
|
|
40 |
|
41 |
.. code-block:: php
|
42 |
|
43 |
-
$twig = new
|
44 |
-
$twig->getExtension('
|
45 |
|
46 |
// before Twig 1.26
|
47 |
$twig->getExtension('core')->setTimezone('Europe/Paris');
|
40 |
|
41 |
.. code-block:: php
|
42 |
|
43 |
+
$twig = new \Twig\Environment($loader);
|
44 |
+
$twig->getExtension('\Twig\Extension\CoreExtension')->setTimezone('Europe/Paris');
|
45 |
|
46 |
// before Twig 1.26
|
47 |
$twig->getExtension('core')->setTimezone('Europe/Paris');
|
vendor/twig/twig/doc/functions/dump.rst
CHANGED
@@ -15,14 +15,14 @@ introspecting its variables:
|
|
15 |
.. note::
|
16 |
|
17 |
The ``dump`` function is not available by default. You must add the
|
18 |
-
``
|
19 |
environment::
|
20 |
|
21 |
-
$twig = new
|
22 |
'debug' => true,
|
23 |
// ...
|
24 |
]);
|
25 |
-
$twig->addExtension(new
|
26 |
|
27 |
Even when enabled, the ``dump`` function won't display anything if the
|
28 |
``debug`` option on the environment is not enabled (to avoid leaking debug
|
15 |
.. note::
|
16 |
|
17 |
The ``dump`` function is not available by default. You must add the
|
18 |
+
``\Twig\Extension\DebugExtension`` extension explicitly when creating your Twig
|
19 |
environment::
|
20 |
|
21 |
+
$twig = new \Twig\Environment($loader, [
|
22 |
'debug' => true,
|
23 |
// ...
|
24 |
]);
|
25 |
+
$twig->addExtension(new \Twig\Extension\DebugExtension());
|
26 |
|
27 |
Even when enabled, the ``dump`` function won't display anything if the
|
28 |
``debug`` option on the environment is not enabled (to avoid leaking debug
|
vendor/twig/twig/doc/functions/include.rst
CHANGED
@@ -37,8 +37,8 @@ You can disable access to the context by setting ``with_context`` to
|
|
37 |
{# no variables will be accessible #}
|
38 |
{{ include('template.html', with_context = false) }}
|
39 |
|
40 |
-
And if the expression evaluates to a ``
|
41 |
-
``
|
42 |
|
43 |
// {{ include(template) }}
|
44 |
|
37 |
{# no variables will be accessible #}
|
38 |
{{ include('template.html', with_context = false) }}
|
39 |
|
40 |
+
And if the expression evaluates to a ``\Twig\Template`` or a
|
41 |
+
``\Twig\TemplateWrapper`` instance, Twig will use it directly::
|
42 |
|
43 |
// {{ include(template) }}
|
44 |
|
vendor/twig/twig/doc/functions/template_from_string.rst
CHANGED
@@ -14,11 +14,11 @@ The ``template_from_string`` function loads a template from a string:
|
|
14 |
.. note::
|
15 |
|
16 |
The ``template_from_string`` function is not available by default. You
|
17 |
-
must add the ``
|
18 |
creating your Twig environment::
|
19 |
|
20 |
-
$twig = new
|
21 |
-
$twig->addExtension(new
|
22 |
|
23 |
.. note::
|
24 |
|
14 |
.. note::
|
15 |
|
16 |
The ``template_from_string`` function is not available by default. You
|
17 |
+
must add the ``\Twig\Extension\StringLoaderExtension`` extension explicitly when
|
18 |
creating your Twig environment::
|
19 |
|
20 |
+
$twig = new \Twig\Environment(...);
|
21 |
+
$twig->addExtension(new \Twig\Extension\StringLoaderExtension());
|
22 |
|
23 |
.. note::
|
24 |
|
vendor/twig/twig/doc/installation.rst
CHANGED
@@ -109,7 +109,7 @@ Finally, enable the extension in your ``php.ini`` configuration file:
|
|
109 |
And from now on, Twig will automatically compile your templates to take
|
110 |
advantage of the C extension. Note that this extension does not replace the
|
111 |
PHP code but only provides an optimized version of the
|
112 |
-
|
113 |
|
114 |
.. _`download page`: https://github.com/twigphp/Twig/tags
|
115 |
.. _`Composer`: https://getcomposer.org/download/
|
109 |
And from now on, Twig will automatically compile your templates to take
|
110 |
advantage of the C extension. Note that this extension does not replace the
|
111 |
PHP code but only provides an optimized version of the
|
112 |
+
``\Twig\Template::getAttribute()`` method.
|
113 |
|
114 |
.. _`download page`: https://github.com/twigphp/Twig/tags
|
115 |
.. _`Composer`: https://getcomposer.org/download/
|
vendor/twig/twig/doc/internals.rst
CHANGED
@@ -27,27 +27,27 @@ The Lexer
|
|
27 |
---------
|
28 |
|
29 |
The lexer tokenizes a template source code into a token stream (each token is
|
30 |
-
an instance of
|
31 |
-
``
|
32 |
-
|
33 |
-
*
|
34 |
-
*
|
35 |
-
*
|
36 |
-
*
|
37 |
-
*
|
38 |
-
*
|
39 |
-
*
|
40 |
-
*
|
41 |
-
*
|
42 |
-
*
|
43 |
|
44 |
You can manually convert a source code into a token stream by calling the
|
45 |
``tokenize()`` method of an environment::
|
46 |
|
47 |
-
$stream = $twig->tokenize(new
|
48 |
|
49 |
.. versionadded:: 1.27
|
50 |
-
``
|
51 |
identifier directly on previous versions.
|
52 |
|
53 |
As the stream has a ``__toString()`` method, you can have a textual
|
@@ -67,7 +67,7 @@ Here is the output for the ``Hello {{ name }}`` template:
|
|
67 |
|
68 |
.. note::
|
69 |
|
70 |
-
The default lexer (``
|
71 |
the ``setLexer()`` method::
|
72 |
|
73 |
$twig->setLexer($lexer);
|
@@ -76,7 +76,7 @@ The Parser
|
|
76 |
----------
|
77 |
|
78 |
The parser converts the token stream into an AST (Abstract Syntax Tree), or a
|
79 |
-
node tree (an instance of ``
|
80 |
the basic nodes like: ``for``, ``if``, ... and the expression nodes.
|
81 |
|
82 |
You can manually convert a token stream into a node tree by calling the
|
@@ -92,16 +92,16 @@ Here is the output for the ``Hello {{ name }}`` template:
|
|
92 |
|
93 |
.. code-block:: text
|
94 |
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
)
|
100 |
)
|
101 |
|
102 |
.. note::
|
103 |
|
104 |
-
The default parser (``
|
105 |
``setParser()`` method::
|
106 |
|
107 |
$twig->setParser($parser);
|
@@ -122,7 +122,7 @@ The generated template for a ``Hello {{ name }}`` template reads as follows
|
|
122 |
using)::
|
123 |
|
124 |
/* Hello {{ name }} */
|
125 |
-
class __TwigTemplate_1121b6f109fe93ebe8c6e22e3712bceb extends
|
126 |
{
|
127 |
protected function doDisplay(array $context, array $blocks = [])
|
128 |
{
|
@@ -136,7 +136,7 @@ using)::
|
|
136 |
|
137 |
.. note::
|
138 |
|
139 |
-
The default compiler (``
|
140 |
``setCompiler()`` method::
|
141 |
|
142 |
$twig->setCompiler($compiler);
|
27 |
---------
|
28 |
|
29 |
The lexer tokenizes a template source code into a token stream (each token is
|
30 |
+
an instance of ``\Twig\Token``, and the stream is an instance of
|
31 |
+
``\Twig\TokenStream``). The default lexer recognizes 13 different token types:
|
32 |
+
|
33 |
+
* ``\Twig\Token::BLOCK_START_TYPE``, ``\Twig\Token::BLOCK_END_TYPE``: Delimiters for blocks (``{% %}``)
|
34 |
+
* ``\Twig\Token::VAR_START_TYPE``, ``\Twig\Token::VAR_END_TYPE``: Delimiters for variables (``{{ }}``)
|
35 |
+
* ``\Twig\Token::TEXT_TYPE``: A text outside an expression;
|
36 |
+
* ``\Twig\Token::NAME_TYPE``: A name in an expression;
|
37 |
+
* ``\Twig\Token::NUMBER_TYPE``: A number in an expression;
|
38 |
+
* ``\Twig\Token::STRING_TYPE``: A string in an expression;
|
39 |
+
* ``\Twig\Token::OPERATOR_TYPE``: An operator;
|
40 |
+
* ``\Twig\Token::PUNCTUATION_TYPE``: A punctuation sign;
|
41 |
+
* ``\Twig\Token::INTERPOLATION_START_TYPE``, ``\Twig\Token::INTERPOLATION_END_TYPE`` (as of Twig 1.5): Delimiters for string interpolation;
|
42 |
+
* ``\Twig\Token::EOF_TYPE``: Ends of template.
|
43 |
|
44 |
You can manually convert a source code into a token stream by calling the
|
45 |
``tokenize()`` method of an environment::
|
46 |
|
47 |
+
$stream = $twig->tokenize(new \Twig\Source($source, $identifier));
|
48 |
|
49 |
.. versionadded:: 1.27
|
50 |
+
``\Twig\Source`` was introduced in version 1.27, pass the source and the
|
51 |
identifier directly on previous versions.
|
52 |
|
53 |
As the stream has a ``__toString()`` method, you can have a textual
|
67 |
|
68 |
.. note::
|
69 |
|
70 |
+
The default lexer (``\Twig\Lexer``) can be changed by calling
|
71 |
the ``setLexer()`` method::
|
72 |
|
73 |
$twig->setLexer($lexer);
|
76 |
----------
|
77 |
|
78 |
The parser converts the token stream into an AST (Abstract Syntax Tree), or a
|
79 |
+
node tree (an instance of ``\Twig\Node\ModuleNode``). The core extension defines
|
80 |
the basic nodes like: ``for``, ``if``, ... and the expression nodes.
|
81 |
|
82 |
You can manually convert a token stream into a node tree by calling the
|
92 |
|
93 |
.. code-block:: text
|
94 |
|
95 |
+
\Twig\Node\ModuleNode(
|
96 |
+
\Twig\Node\TextNode(Hello )
|
97 |
+
\Twig\Node\PrintNode(
|
98 |
+
\Twig\Node\Expression\NameExpression(name)
|
99 |
)
|
100 |
)
|
101 |
|
102 |
.. note::
|
103 |
|
104 |
+
The default parser (``\Twig\TokenParser\AbstractTokenParser``) can be changed by calling the
|
105 |
``setParser()`` method::
|
106 |
|
107 |
$twig->setParser($parser);
|
122 |
using)::
|
123 |
|
124 |
/* Hello {{ name }} */
|
125 |
+
class __TwigTemplate_1121b6f109fe93ebe8c6e22e3712bceb extends \Twig\Template
|
126 |
{
|
127 |
protected function doDisplay(array $context, array $blocks = [])
|
128 |
{
|
136 |
|
137 |
.. note::
|
138 |
|
139 |
+
The default compiler (``\Twig\Compiler``) can be changed by calling the
|
140 |
``setCompiler()`` method::
|
141 |
|
142 |
$twig->setCompiler($compiler);
|
vendor/twig/twig/doc/intro.rst
CHANGED
@@ -55,15 +55,15 @@ This section gives you a brief introduction to the PHP API for Twig.
|
|
55 |
|
56 |
require_once '/path/to/vendor/autoload.php';
|
57 |
|
58 |
-
$loader = new
|
59 |
'index' => 'Hello {{ name }}!',
|
60 |
]);
|
61 |
-
$twig = new
|
62 |
|
63 |
echo $twig->render('index', ['name' => 'Fabien']);
|
64 |
|
65 |
-
Twig uses a loader (``
|
66 |
-
environment (``
|
67 |
|
68 |
The ``render()`` method loads the template passed as a first argument and
|
69 |
renders it with the variables passed as a second argument.
|
@@ -71,8 +71,8 @@ renders it with the variables passed as a second argument.
|
|
71 |
As templates are generally stored on the filesystem, Twig also comes with a
|
72 |
filesystem loader::
|
73 |
|
74 |
-
$loader = new
|
75 |
-
$twig = new
|
76 |
'cache' => '/path/to/compilation_cache',
|
77 |
]);
|
78 |
|
55 |
|
56 |
require_once '/path/to/vendor/autoload.php';
|
57 |
|
58 |
+
$loader = new \Twig\Loader\ArrayLoader([
|
59 |
'index' => 'Hello {{ name }}!',
|
60 |
]);
|
61 |
+
$twig = new \Twig\Environment($loader);
|
62 |
|
63 |
echo $twig->render('index', ['name' => 'Fabien']);
|
64 |
|
65 |
+
Twig uses a loader (``\Twig\Loader\ArrayLoader``) to locate templates, and an
|
66 |
+
environment (``\Twig\Environment``) to store the configuration.
|
67 |
|
68 |
The ``render()`` method loads the template passed as a first argument and
|
69 |
renders it with the variables passed as a second argument.
|
71 |
As templates are generally stored on the filesystem, Twig also comes with a
|
72 |
filesystem loader::
|
73 |
|
74 |
+
$loader = new \Twig\Loader\FilesystemLoader('/path/to/templates');
|
75 |
+
$twig = new \Twig\Environment($loader, [
|
76 |
'cache' => '/path/to/compilation_cache',
|
77 |
]);
|
78 |
|
vendor/twig/twig/doc/recipes.rst
CHANGED
@@ -20,7 +20,7 @@ run a script along the lines of the following::
|
|
20 |
|
21 |
$twig = create_your_twig_env();
|
22 |
|
23 |
-
$deprecations = new
|
24 |
|
25 |
print_r($deprecations->collectDir(__DIR__.'/templates'));
|
26 |
|
@@ -32,7 +32,7 @@ catches deprecation notices, and return them.
|
|
32 |
If your templates are not stored on the filesystem, use the ``collect()``
|
33 |
method instead. ``collect()`` takes a ``Traversable`` which must return
|
34 |
template names as keys and template contents as values (as done by
|
35 |
-
``
|
36 |
|
37 |
However, this code won't find all deprecations (like using deprecated some Twig
|
38 |
classes). To catch all notices, register a custom error handler like the one
|
@@ -161,9 +161,9 @@ syntax. But for specific projects, it can make sense to change the defaults.
|
|
161 |
|
162 |
To change the block delimiters, you need to create your own lexer object::
|
163 |
|
164 |
-
$twig = new
|
165 |
|
166 |
-
$lexer = new
|
167 |
'tag_comment' => ['{#', '#}'],
|
168 |
'tag_block' => ['{%', '%}'],
|
169 |
'tag_variable' => ['{{', '}}'],
|
@@ -175,21 +175,21 @@ Here are some configuration example that simulates some other template engines
|
|
175 |
syntax::
|
176 |
|
177 |
// Ruby erb syntax
|
178 |
-
$lexer = new
|
179 |
'tag_comment' => ['<%#', '%>'],
|
180 |
'tag_block' => ['<%', '%>'],
|
181 |
'tag_variable' => ['<%=', '%>'],
|
182 |
]);
|
183 |
|
184 |
// SGML Comment Syntax
|
185 |
-
$lexer = new
|
186 |
'tag_comment' => ['<!--#', '-->'],
|
187 |
'tag_block' => ['<!--', '-->'],
|
188 |
'tag_variable' => ['${', '}'],
|
189 |
]);
|
190 |
|
191 |
// Smarty like
|
192 |
-
$lexer = new
|
193 |
'tag_comment' => ['{*', '*}'],
|
194 |
'tag_block' => ['{', '}'],
|
195 |
'tag_variable' => ['{$', '}'],
|
@@ -270,7 +270,7 @@ Defining undefined Functions and Filters on the Fly
|
|
270 |
---------------------------------------------------
|
271 |
|
272 |
When a function (or a filter) is not defined, Twig defaults to throw a
|
273 |
-
``
|
274 |
valid PHP callable) which should return a function (or a filter).
|
275 |
|
276 |
For filters, register callbacks with ``registerUndefinedFilterCallback()``.
|
@@ -280,7 +280,7 @@ For functions, use ``registerUndefinedFunctionCallback()``::
|
|
280 |
// don't try this at home as it's not secure at all!
|
281 |
$twig->registerUndefinedFunctionCallback(function ($name) {
|
282 |
if (function_exists($name)) {
|
283 |
-
return new
|
284 |
}
|
285 |
|
286 |
return false;
|
@@ -306,10 +306,10 @@ saving it. If the template code is stored in a `$template` variable, here is
|
|
306 |
how you can do it::
|
307 |
|
308 |
try {
|
309 |
-
$twig->parse($twig->tokenize(new
|
310 |
|
311 |
// the $template is valid
|
312 |
-
} catch (
|
313 |
// $template contains one or more syntax errors
|
314 |
}
|
315 |
|
@@ -318,16 +318,16 @@ If you iterate over a set of files, you can pass the filename to the
|
|
318 |
|
319 |
foreach ($files as $file) {
|
320 |
try {
|
321 |
-
$twig->parse($twig->tokenize(new
|
322 |
|
323 |
// the $template is valid
|
324 |
-
} catch (
|
325 |
// $template contains one or more syntax errors
|
326 |
}
|
327 |
}
|
328 |
|
329 |
.. versionadded:: 1.27
|
330 |
-
``
|
331 |
identifier directly on previous versions.
|
332 |
|
333 |
.. note::
|
@@ -345,16 +345,16 @@ cache won't update the cache.
|
|
345 |
|
346 |
To get around this, force Twig to invalidate the bytecode cache::
|
347 |
|
348 |
-
$twig = new
|
349 |
-
'cache' => new
|
350 |
// ...
|
351 |
]);
|
352 |
|
353 |
.. note::
|
354 |
|
355 |
-
Before Twig 1.22, you should extend ``
|
356 |
|
357 |
-
class OpCacheAwareTwigEnvironment extends
|
358 |
{
|
359 |
protected function writeCacheFile($file, $content)
|
360 |
{
|
@@ -372,7 +372,7 @@ To get around this, force Twig to invalidate the bytecode cache::
|
|
372 |
Reusing a stateful Node Visitor
|
373 |
-------------------------------
|
374 |
|
375 |
-
When attaching a visitor to a ``
|
376 |
visit *all* templates it compiles. If you need to keep some state information
|
377 |
around, you probably want to reset it when visiting a new template.
|
378 |
|
@@ -380,9 +380,9 @@ This can be easily achieved with the following code::
|
|
380 |
|
381 |
protected $someTemplateState = [];
|
382 |
|
383 |
-
public function enterNode(Twig_NodeInterface $node,
|
384 |
{
|
385 |
-
if ($node instanceof
|
386 |
// reset the state as we are entering a new template
|
387 |
$this->someTemplateState = [];
|
388 |
}
|
@@ -417,7 +417,7 @@ We have created a simple ``templates`` table that hosts two templates:
|
|
417 |
|
418 |
Now, let's define a loader able to use this database::
|
419 |
|
420 |
-
class DatabaseTwigLoader implements
|
421 |
{
|
422 |
protected $dbh;
|
423 |
|
@@ -429,23 +429,23 @@ Now, let's define a loader able to use this database::
|
|
429 |
public function getSource($name)
|
430 |
{
|
431 |
if (false === $source = $this->getValue('source', $name)) {
|
432 |
-
throw new
|
433 |
}
|
434 |
|
435 |
return $source;
|
436 |
}
|
437 |
|
438 |
-
//
|
439 |
public function getSourceContext($name)
|
440 |
{
|
441 |
if (false === $source = $this->getValue('source', $name)) {
|
442 |
-
throw new
|
443 |
}
|
444 |
|
445 |
-
return new
|
446 |
}
|
447 |
|
448 |
-
//
|
449 |
public function exists($name)
|
450 |
{
|
451 |
return $name === $this->getValue('name', $name);
|
@@ -477,7 +477,7 @@ Now, let's define a loader able to use this database::
|
|
477 |
Finally, here is an example on how you can use it::
|
478 |
|
479 |
$loader = new DatabaseTwigLoader($dbh);
|
480 |
-
$twig = new
|
481 |
|
482 |
echo $twig->render('index.twig', ['name' => 'Fabien']);
|
483 |
|
@@ -487,7 +487,7 @@ Using different Template Sources
|
|
487 |
This recipe is the continuation of the previous one. Even if you store the
|
488 |
contributed templates in a database, you might want to keep the original/base
|
489 |
templates on the filesystem. When templates can be loaded from different
|
490 |
-
sources, you need to use the ``
|
491 |
|
492 |
As you can see in the previous recipe, we reference the template in the exact
|
493 |
same way as we would have done it with a regular filesystem loader. This is
|
@@ -496,12 +496,12 @@ filesystem, or any other loader for that matter: the template name should be a
|
|
496 |
logical name, and not the path from the filesystem::
|
497 |
|
498 |
$loader1 = new DatabaseTwigLoader($dbh);
|
499 |
-
$loader2 = new
|
500 |
'base.twig' => '{% block content %}{% endblock %}',
|
501 |
]);
|
502 |
-
$loader = new
|
503 |
|
504 |
-
$twig = new
|
505 |
|
506 |
echo $twig->render('index.twig', ['name' => 'Fabien']);
|
507 |
|
@@ -513,14 +513,14 @@ Loading a Template from a String
|
|
513 |
|
514 |
From a template, you can easily load a template stored in a string via the
|
515 |
``template_from_string`` function (available as of Twig 1.11 via the
|
516 |
-
``
|
517 |
|
518 |
.. code-block:: jinja
|
519 |
|
520 |
{{ include(template_from_string("Hello {{ name }}")) }}
|
521 |
|
522 |
From PHP, it's also possible to load a template stored in a string via
|
523 |
-
|
524 |
|
525 |
$template = $twig->createTemplate('hello {{ name }}');
|
526 |
echo $template->render(['name' => 'Fabien']);
|
@@ -561,7 +561,7 @@ include in your templates:
|
|
561 |
|
562 |
.. code-block:: php
|
563 |
|
564 |
-
$env->setLexer(new
|
565 |
'tag_variable' => ['{[', ']}'],
|
566 |
]));
|
567 |
|
20 |
|
21 |
$twig = create_your_twig_env();
|
22 |
|
23 |
+
$deprecations = new \Twig\Util\DeprecationCollector($twig);
|
24 |
|
25 |
print_r($deprecations->collectDir(__DIR__.'/templates'));
|
26 |
|
32 |
If your templates are not stored on the filesystem, use the ``collect()``
|
33 |
method instead. ``collect()`` takes a ``Traversable`` which must return
|
34 |
template names as keys and template contents as values (as done by
|
35 |
+
``\Twig\Util\TemplateDirIterator``).
|
36 |
|
37 |
However, this code won't find all deprecations (like using deprecated some Twig
|
38 |
classes). To catch all notices, register a custom error handler like the one
|
161 |
|
162 |
To change the block delimiters, you need to create your own lexer object::
|
163 |
|
164 |
+
$twig = new \Twig\Environment();
|
165 |
|
166 |
+
$lexer = new \Twig\Lexer($twig, [
|
167 |
'tag_comment' => ['{#', '#}'],
|
168 |
'tag_block' => ['{%', '%}'],
|
169 |
'tag_variable' => ['{{', '}}'],
|
175 |
syntax::
|
176 |
|
177 |
// Ruby erb syntax
|
178 |
+
$lexer = new \Twig\Lexer($twig, [
|
179 |
'tag_comment' => ['<%#', '%>'],
|
180 |
'tag_block' => ['<%', '%>'],
|
181 |
'tag_variable' => ['<%=', '%>'],
|
182 |
]);
|
183 |
|
184 |
// SGML Comment Syntax
|
185 |
+
$lexer = new \Twig\Lexer($twig, [
|
186 |
'tag_comment' => ['<!--#', '-->'],
|
187 |
'tag_block' => ['<!--', '-->'],
|
188 |
'tag_variable' => ['${', '}'],
|
189 |
]);
|
190 |
|
191 |
// Smarty like
|
192 |
+
$lexer = new \Twig\Lexer($twig, [
|
193 |
'tag_comment' => ['{*', '*}'],
|
194 |
'tag_block' => ['{', '}'],
|
195 |
'tag_variable' => ['{$', '}'],
|
270 |
---------------------------------------------------
|
271 |
|
272 |
When a function (or a filter) is not defined, Twig defaults to throw a
|
273 |
+
``\Twig\Error\SyntaxError`` exception. However, it can also call a `callback`_ (any
|
274 |
valid PHP callable) which should return a function (or a filter).
|
275 |
|
276 |
For filters, register callbacks with ``registerUndefinedFilterCallback()``.
|
280 |
// don't try this at home as it's not secure at all!
|
281 |
$twig->registerUndefinedFunctionCallback(function ($name) {
|
282 |
if (function_exists($name)) {
|
283 |
+
return new \Twig\TwigFunction($name, $name);
|
284 |
}
|
285 |
|
286 |
return false;
|
306 |
how you can do it::
|
307 |
|
308 |
try {
|
309 |
+
$twig->parse($twig->tokenize(new \Twig\Source($template)));
|
310 |
|
311 |
// the $template is valid
|
312 |
+
} catch (\Twig\Error\SyntaxError $e) {
|
313 |
// $template contains one or more syntax errors
|
314 |
}
|
315 |
|
318 |
|
319 |
foreach ($files as $file) {
|
320 |
try {
|
321 |
+
$twig->parse($twig->tokenize(new \Twig\Source($template, $file->getFilename(), $file)));
|
322 |
|
323 |
// the $template is valid
|
324 |
+
} catch (\Twig\Error\SyntaxError $e) {
|
325 |
// $template contains one or more syntax errors
|
326 |
}
|
327 |
}
|
328 |
|
329 |
.. versionadded:: 1.27
|
330 |
+
``\Twig\Source`` was introduced in version 1.27, pass the source and the
|
331 |
identifier directly on previous versions.
|
332 |
|
333 |
.. note::
|
345 |
|
346 |
To get around this, force Twig to invalidate the bytecode cache::
|
347 |
|
348 |
+
$twig = new \Twig\Environment($loader, [
|
349 |
+
'cache' => new \Twig\Cache\FilesystemCache('/some/cache/path', \Twig\Cache\FilesystemCache::FORCE_BYTECODE_INVALIDATION),
|
350 |
// ...
|
351 |
]);
|
352 |
|
353 |
.. note::
|
354 |
|
355 |
+
Before Twig 1.22, you should extend ``\Twig\Environment`` instead::
|
356 |
|
357 |
+
class OpCacheAwareTwigEnvironment extends \Twig\Environment
|
358 |
{
|
359 |
protected function writeCacheFile($file, $content)
|
360 |
{
|
372 |
Reusing a stateful Node Visitor
|
373 |
-------------------------------
|
374 |
|
375 |
+
When attaching a visitor to a ``\Twig\Environment`` instance, Twig uses it to
|
376 |
visit *all* templates it compiles. If you need to keep some state information
|
377 |
around, you probably want to reset it when visiting a new template.
|
378 |
|
380 |
|
381 |
protected $someTemplateState = [];
|
382 |
|
383 |
+
public function enterNode(Twig_NodeInterface $node, \Twig\Environment $env)
|
384 |
{
|
385 |
+
if ($node instanceof \Twig\Node\ModuleNode) {
|
386 |
// reset the state as we are entering a new template
|
387 |
$this->someTemplateState = [];
|
388 |
}
|
417 |
|
418 |
Now, let's define a loader able to use this database::
|
419 |
|
420 |
+
class DatabaseTwigLoader implements \Twig\Loader\LoaderInterface, \Twig\Loader\ExistsLoaderInterface, \Twig\Loader\SourceContextLoaderInterface
|
421 |
{
|
422 |
protected $dbh;
|
423 |
|
429 |
public function getSource($name)
|
430 |
{
|
431 |
if (false === $source = $this->getValue('source', $name)) {
|
432 |
+
throw new \Twig\Error\LoaderError(sprintf('Template "%s" does not exist.', $name));
|
433 |
}
|
434 |
|
435 |
return $source;
|
436 |
}
|
437 |
|
438 |
+
// \Twig\Loader\SourceContextLoaderInterface as of Twig 1.27
|
439 |
public function getSourceContext($name)
|
440 |
{
|
441 |
if (false === $source = $this->getValue('source', $name)) {
|
442 |
+
throw new \Twig\Error\LoaderError(sprintf('Template "%s" does not exist.', $name));
|
443 |
}
|
444 |
|
445 |
+
return new \Twig\Source($source, $name);
|
446 |
}
|
447 |
|
448 |
+
// \Twig\Loader\ExistsLoaderInterface as of Twig 1.11
|
449 |
public function exists($name)
|
450 |
{
|
451 |
return $name === $this->getValue('name', $name);
|
477 |
Finally, here is an example on how you can use it::
|
478 |
|
479 |
$loader = new DatabaseTwigLoader($dbh);
|
480 |
+
$twig = new \Twig\Environment($loader);
|
481 |
|
482 |
echo $twig->render('index.twig', ['name' => 'Fabien']);
|
483 |
|
487 |
This recipe is the continuation of the previous one. Even if you store the
|
488 |
contributed templates in a database, you might want to keep the original/base
|
489 |
templates on the filesystem. When templates can be loaded from different
|
490 |
+
sources, you need to use the ``\Twig\Loader\ChainLoader`` loader.
|
491 |
|
492 |
As you can see in the previous recipe, we reference the template in the exact
|
493 |
same way as we would have done it with a regular filesystem loader. This is
|
496 |
logical name, and not the path from the filesystem::
|
497 |
|
498 |
$loader1 = new DatabaseTwigLoader($dbh);
|
499 |
+
$loader2 = new \Twig\Loader\ArrayLoader([
|
500 |
'base.twig' => '{% block content %}{% endblock %}',
|
501 |
]);
|
502 |
+
$loader = new \Twig\Loader\ChainLoader([$loader1, $loader2]);
|
503 |
|
504 |
+
$twig = new \Twig\Environment($loader);
|
505 |
|
506 |
echo $twig->render('index.twig', ['name' => 'Fabien']);
|
507 |
|
513 |
|
514 |
From a template, you can easily load a template stored in a string via the
|
515 |
``template_from_string`` function (available as of Twig 1.11 via the
|
516 |
+
``\Twig\Extension\StringLoaderExtension`` extension):
|
517 |
|
518 |
.. code-block:: jinja
|
519 |
|
520 |
{{ include(template_from_string("Hello {{ name }}")) }}
|
521 |
|
522 |
From PHP, it's also possible to load a template stored in a string via
|
523 |
+
``\Twig\Environment::createTemplate()`` (available as of Twig 1.18)::
|
524 |
|
525 |
$template = $twig->createTemplate('hello {{ name }}');
|
526 |
echo $template->render(['name' => 'Fabien']);
|
561 |
|
562 |
.. code-block:: php
|
563 |
|
564 |
+
$env->setLexer(new \Twig\Lexer($env, [
|
565 |
'tag_variable' => ['{[', ']}'],
|
566 |
]));
|
567 |
|
vendor/twig/twig/doc/tags/extends.rst
CHANGED
@@ -153,7 +153,7 @@ Twig supports dynamic inheritance by using a variable as the base template:
|
|
153 |
|
154 |
{% extends some_var %}
|
155 |
|
156 |
-
If the variable evaluates to a ``
|
157 |
instance, Twig will use it as the parent template::
|
158 |
|
159 |
// {% extends layout %}
|
153 |
|
154 |
{% extends some_var %}
|
155 |
|
156 |
+
If the variable evaluates to a ``\Twig\Template`` or a ``\Twig\TemplateWrapper``
|
157 |
instance, Twig will use it as the parent template::
|
158 |
|
159 |
// {% extends layout %}
|
vendor/twig/twig/doc/tags/filter.rst
CHANGED
@@ -10,11 +10,11 @@ data. Just wrap the code in the special ``filter`` section:
|
|
10 |
This text becomes uppercase
|
11 |
{% endfilter %}
|
12 |
|
13 |
-
You can also chain filters:
|
14 |
|
15 |
.. code-block:: jinja
|
16 |
|
17 |
-
{% filter lower|escape %}
|
18 |
<strong>SOME TEXT</strong>
|
19 |
{% endfilter %}
|
20 |
|
10 |
This text becomes uppercase
|
11 |
{% endfilter %}
|
12 |
|
13 |
+
You can also chain filters and pass arguments to them:
|
14 |
|
15 |
.. code-block:: jinja
|
16 |
|
17 |
+
{% filter lower|escape('html') %}
|
18 |
<strong>SOME TEXT</strong>
|
19 |
{% endfilter %}
|
20 |
|
vendor/twig/twig/doc/tags/include.rst
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
===========
|
3 |
|
4 |
The ``include`` statement includes a template and returns the rendered content
|
5 |
-
of that file
|
6 |
|
7 |
.. code-block:: jinja
|
8 |
|
@@ -10,6 +10,30 @@ of that file into the current namespace:
|
|
10 |
Body
|
11 |
{% include 'footer.html' %}
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
Included templates have access to the variables of the active context.
|
14 |
|
15 |
If you are using the filesystem loader, the templates are looked for in the
|
@@ -50,8 +74,8 @@ The template name can be any valid Twig expression:
|
|
50 |
{% include some_var %}
|
51 |
{% include ajax ? 'ajax.html' : 'not_ajax.html' %}
|
52 |
|
53 |
-
And if the expression evaluates to a ``
|
54 |
-
``
|
55 |
|
56 |
// {% include template %}
|
57 |
|
2 |
===========
|
3 |
|
4 |
The ``include`` statement includes a template and returns the rendered content
|
5 |
+
of that file:
|
6 |
|
7 |
.. code-block:: jinja
|
8 |
|
10 |
Body
|
11 |
{% include 'footer.html' %}
|
12 |
|
13 |
+
.. note::
|
14 |
+
|
15 |
+
As of Twig 1.12, it is recommended to use the
|
16 |
+
:doc:`include<../functions/include>` function instead as it provides the
|
17 |
+
same features with a bit more flexibility:
|
18 |
+
|
19 |
+
* The ``include`` function is semantically more "correct" (including a
|
20 |
+
template outputs its rendered contents in the current scope; a tag should
|
21 |
+
not display anything);
|
22 |
+
|
23 |
+
* The rendered template can be more easily stored in a variable when using
|
24 |
+
the ``include`` function:
|
25 |
+
|
26 |
+
.. code-block:: jinja
|
27 |
+
|
28 |
+
{% set content %}{% include 'template.html' %}{% endset %}
|
29 |
+
|
30 |
+
{# vs #}
|
31 |
+
|
32 |
+
{% set content = include('template.html') %}
|
33 |
+
|
34 |
+
* The ``include`` function does not impose any specific order for
|
35 |
+
arguments thanks to :ref:`named arguments <named-arguments>`.
|
36 |
+
|
37 |
Included templates have access to the variables of the active context.
|
38 |
|
39 |
If you are using the filesystem loader, the templates are looked for in the
|
74 |
{% include some_var %}
|
75 |
{% include ajax ? 'ajax.html' : 'not_ajax.html' %}
|
76 |
|
77 |
+
And if the expression evaluates to a ``\Twig\Template`` or a
|
78 |
+
``\Twig\TemplateWrapper`` instance, Twig will use it directly::
|
79 |
|
80 |
// {% include template %}
|
81 |
|
vendor/twig/twig/doc/tags/set.rst
CHANGED
@@ -18,7 +18,7 @@ any other ones:
|
|
18 |
{# displays bar #}
|
19 |
{{ foo }}
|
20 |
|
21 |
-
The assigned value can be any valid :ref:`Twig
|
22 |
<twig-expressions>`:
|
23 |
|
24 |
.. code-block:: jinja
|
18 |
{# displays bar #}
|
19 |
{{ foo }}
|
20 |
|
21 |
+
The assigned value can be any valid :ref:`Twig expression
|
22 |
<twig-expressions>`:
|
23 |
|
24 |
.. code-block:: jinja
|
vendor/twig/twig/doc/templates.rst
CHANGED
@@ -196,6 +196,8 @@ progression of integers:
|
|
196 |
Go to the :doc:`functions<functions/index>` page to learn more about the
|
197 |
built-in functions.
|
198 |
|
|
|
|
|
199 |
Named Arguments
|
200 |
---------------
|
201 |
|
@@ -314,7 +316,7 @@ will be available in the included template too:
|
|
314 |
The included template ``render_box.html`` is able to access the ``box`` variable.
|
315 |
|
316 |
The name of the template depends on the template loader. For instance, the
|
317 |
-
``
|
318 |
filename. You can access templates in subdirectories with a slash:
|
319 |
|
320 |
.. code-block:: jinja
|
196 |
Go to the :doc:`functions<functions/index>` page to learn more about the
|
197 |
built-in functions.
|
198 |
|
199 |
+
.. _named-arguments:
|
200 |
+
|
201 |
Named Arguments
|
202 |
---------------
|
203 |
|
316 |
The included template ``render_box.html`` is able to access the ``box`` variable.
|
317 |
|
318 |
The name of the template depends on the template loader. For instance, the
|
319 |
+
``\Twig\Loader\FilesystemLoader`` allows you to access other templates by giving the
|
320 |
filename. You can access templates in subdirectories with a slash:
|
321 |
|
322 |
.. code-block:: jinja
|
vendor/twig/twig/ext/twig/php_twig.h
CHANGED
@@ -15,7 +15,7 @@
|
|
15 |
#ifndef PHP_TWIG_H
|
16 |
#define PHP_TWIG_H
|
17 |
|
18 |
-
#define PHP_TWIG_VERSION "1.
|
19 |
|
20 |
#include "php.h"
|
21 |
|
15 |
#ifndef PHP_TWIG_H
|
16 |
#define PHP_TWIG_H
|
17 |
|
18 |
+
#define PHP_TWIG_VERSION "1.38.0-DEV"
|
19 |
|
20 |
#include "php.h"
|
21 |
|
vendor/twig/twig/ext/twig/twig.c
CHANGED
@@ -733,7 +733,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
733 |
|
734 |
/*
|
735 |
// array
|
736 |
-
if (
|
737 |
$arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
|
738 |
|
739 |
if ((is_array($object) && array_key_exists($arrayItem, $object))
|
@@ -771,7 +771,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
771 |
return;
|
772 |
}
|
773 |
/*
|
774 |
-
if (
|
775 |
if ($isDefinedTest) {
|
776 |
return false;
|
777 |
}
|
@@ -799,7 +799,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
799 |
} else {
|
800 |
$message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object)));
|
801 |
}
|
802 |
-
} elseif (
|
803 |
if (null === $object) {
|
804 |
$message = sprintf('Impossible to access a key ("%s") on a null variable', $item);
|
805 |
} else {
|
@@ -810,7 +810,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
810 |
} else {
|
811 |
$message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
|
812 |
}
|
813 |
-
throw new
|
814 |
}
|
815 |
}
|
816 |
*/
|
@@ -876,7 +876,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
876 |
$message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
|
877 |
}
|
878 |
|
879 |
-
throw new
|
880 |
}
|
881 |
*/
|
882 |
if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
|
@@ -916,14 +916,14 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
916 |
|
917 |
/*
|
918 |
// object property
|
919 |
-
if (
|
920 |
if (isset($object->$item) || array_key_exists((string) $item, $object)) {
|
921 |
if ($isDefinedTest) {
|
922 |
return true;
|
923 |
}
|
924 |
|
925 |
-
if ($this->env->hasExtension('
|
926 |
-
$this->env->getExtension('
|
927 |
}
|
928 |
|
929 |
return $object->$item;
|
@@ -958,7 +958,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
958 |
// object method
|
959 |
if (!isset(self::$cache[$class]['methods'])) {
|
960 |
if ($object instanceof self) {
|
961 |
-
$ref = new ReflectionClass($class);
|
962 |
$methods = [];
|
963 |
|
964 |
foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $refMethod) {
|
@@ -1029,7 +1029,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
1029 |
return null;
|
1030 |
}
|
1031 |
|
1032 |
-
throw new
|
1033 |
}
|
1034 |
|
1035 |
if ($isDefinedTest) {
|
@@ -1061,8 +1061,8 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
1061 |
RETURN_TRUE;
|
1062 |
}
|
1063 |
/*
|
1064 |
-
if ($this->env->hasExtension('
|
1065 |
-
$this->env->getExtension('
|
1066 |
}
|
1067 |
*/
|
1068 |
MAKE_STD_ZVAL(zmethod);
|
@@ -1082,7 +1082,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
1082 |
// to call is not supported. If ignoreStrictCheck is true, we should return null.
|
1083 |
try {
|
1084 |
$ret = call_user_func_array([$object, $method], $arguments);
|
1085 |
-
} catch (BadMethodCallException $e) {
|
1086 |
if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) {
|
1087 |
return null;
|
1088 |
}
|
@@ -1117,7 +1117,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|
1117 |
}
|
1118 |
@trigger_error($message, E_USER_DEPRECATED);
|
1119 |
|
1120 |
-
return $ret === '' ? '' : new
|
1121 |
}
|
1122 |
|
1123 |
return $ret;
|
733 |
|
734 |
/*
|
735 |
// array
|
736 |
+
if (\Twig\Template::METHOD_CALL !== $type) {
|
737 |
$arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
|
738 |
|
739 |
if ((is_array($object) && array_key_exists($arrayItem, $object))
|
771 |
return;
|
772 |
}
|
773 |
/*
|
774 |
+
if (\Twig\Template::ARRAY_CALL === $type) {
|
775 |
if ($isDefinedTest) {
|
776 |
return false;
|
777 |
}
|
799 |
} else {
|
800 |
$message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object)));
|
801 |
}
|
802 |
+
} elseif (\Twig\Template::ARRAY_CALL === $type) {
|
803 |
if (null === $object) {
|
804 |
$message = sprintf('Impossible to access a key ("%s") on a null variable', $item);
|
805 |
} else {
|
810 |
} else {
|
811 |
$message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
|
812 |
}
|
813 |
+
throw new \Twig\Error\RuntimeError($message, -1, $this->getTemplateName());
|
814 |
}
|
815 |
}
|
816 |
*/
|
876 |
$message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
|
877 |
}
|
878 |
|
879 |
+
throw new \Twig\Error\RuntimeError($message, -1, $this->getTemplateName());
|
880 |
}
|
881 |
*/
|
882 |
if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
|
916 |
|
917 |
/*
|
918 |
// object property
|
919 |
+
if (\Twig\Template::METHOD_CALL !== $type && !$object instanceof \Twig\Template) {
|
920 |
if (isset($object->$item) || array_key_exists((string) $item, $object)) {
|
921 |
if ($isDefinedTest) {
|
922 |
return true;
|
923 |
}
|
924 |
|
925 |
+
if ($this->env->hasExtension('\Twig\Extension\SandboxExtension')) {
|
926 |
+
$this->env->getExtension('\Twig\Extension\SandboxExtension')->checkPropertyAllowed($object, $item);
|
927 |
}
|
928 |
|
929 |
return $object->$item;
|
958 |
// object method
|
959 |
if (!isset(self::$cache[$class]['methods'])) {
|
960 |
if ($object instanceof self) {
|
961 |
+
$ref = new \ReflectionClass($class);
|
962 |
$methods = [];
|
963 |
|
964 |
foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $refMethod) {
|
1029 |
return null;
|
1030 |
}
|
1031 |
|
1032 |
+
throw new \Twig\Error\RuntimeError(sprintf('Method "%s" for object "%s" does not exist.', $item, get_class($object)), -1, $this->getTemplateName());
|
1033 |
}
|
1034 |
|
1035 |
if ($isDefinedTest) {
|
1061 |
RETURN_TRUE;
|
1062 |
}
|
1063 |
/*
|
1064 |
+
if ($this->env->hasExtension('\Twig\Extension\SandboxExtension')) {
|
1065 |
+
$this->env->getExtension('\Twig\Extension\SandboxExtension')->checkMethodAllowed($object, $method);
|
1066 |
}
|
1067 |
*/
|
1068 |
MAKE_STD_ZVAL(zmethod);
|
1082 |
// to call is not supported. If ignoreStrictCheck is true, we should return null.
|
1083 |
try {
|
1084 |
$ret = call_user_func_array([$object, $method], $arguments);
|
1085 |
+
} catch (\BadMethodCallException $e) {
|
1086 |
if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) {
|
1087 |
return null;
|
1088 |
}
|
1117 |
}
|
1118 |
@trigger_error($message, E_USER_DEPRECATED);
|
1119 |
|
1120 |
+
return $ret === '' ? '' : new \Twig\Markup($ret, $this->env->getCharset());
|
1121 |
}
|
1122 |
|
1123 |
return $ret;
|
vendor/twig/twig/lib/Twig/Autoloader.php
CHANGED
@@ -43,7 +43,7 @@ class Twig_Autoloader
|
|
43 |
return;
|
44 |
}
|
45 |
|
46 |
-
if (is_file($file =
|
47 |
require $file;
|
48 |
}
|
49 |
}
|
43 |
return;
|
44 |
}
|
45 |
|
46 |
+
if (is_file($file = __DIR__.'/../'.str_replace(['_', "\0"], ['/', ''], $class).'.php')) {
|
47 |
require $file;
|
48 |
}
|
49 |
}
|
vendor/twig/twig/lib/Twig/BaseNodeVisitor.php
CHANGED
@@ -9,26 +9,30 @@
|
|
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
|
18 |
{
|
19 |
-
final public function enterNode(Twig_NodeInterface $node,
|
20 |
{
|
21 |
-
if (!$node instanceof
|
22 |
-
throw new LogicException('
|
23 |
}
|
24 |
|
25 |
return $this->doEnterNode($node, $env);
|
26 |
}
|
27 |
|
28 |
-
final public function leaveNode(Twig_NodeInterface $node,
|
29 |
{
|
30 |
-
if (!$node instanceof
|
31 |
-
throw new LogicException('
|
32 |
}
|
33 |
|
34 |
return $this->doLeaveNode($node, $env);
|
@@ -37,16 +41,16 @@ abstract class Twig_BaseNodeVisitor implements Twig_NodeVisitorInterface
|
|
37 |
/**
|
38 |
* Called before child nodes are visited.
|
39 |
*
|
40 |
-
* @return
|
41 |
*/
|
42 |
-
abstract protected function doEnterNode(
|
43 |
|
44 |
/**
|
45 |
* Called after child nodes are visited.
|
46 |
*
|
47 |
-
* @return
|
48 |
*/
|
49 |
-
abstract protected function doLeaveNode(
|
50 |
}
|
51 |
|
52 |
class_alias('Twig_BaseNodeVisitor', 'Twig\NodeVisitor\AbstractNodeVisitor', false);
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Environment;
|
13 |
+
use Twig\Node\Node;
|
14 |
+
use Twig\NodeVisitor\NodeVisitorInterface;
|
15 |
+
|
16 |
/**
|
17 |
* Twig_BaseNodeVisitor can be used to make node visitors compatible with Twig 1.x and 2.x.
|
18 |
*
|
19 |
* @author Fabien Potencier <fabien@symfony.com>
|
20 |
*/
|
21 |
+
abstract class Twig_BaseNodeVisitor implements NodeVisitorInterface
|
22 |
{
|
23 |
+
final public function enterNode(Twig_NodeInterface $node, Environment $env)
|
24 |
{
|
25 |
+
if (!$node instanceof Node) {
|
26 |
+
throw new \LogicException(sprintf('%s only supports Twig_Node instances.', __CLASS__));
|
27 |
}
|
28 |
|
29 |
return $this->doEnterNode($node, $env);
|
30 |
}
|
31 |
|
32 |
+
final public function leaveNode(Twig_NodeInterface $node, Environment $env)
|
33 |
{
|
34 |
+
if (!$node instanceof Node) {
|
35 |
+
throw new \LogicException(sprintf('%s only supports Twig_Node instances.', __CLASS__));
|
36 |
}
|
37 |
|
38 |
return $this->doLeaveNode($node, $env);
|
41 |
/**
|
42 |
* Called before child nodes are visited.
|
43 |
*
|
44 |
+
* @return Node The modified node
|
45 |
*/
|
46 |
+
abstract protected function doEnterNode(Node $node, Environment $env);
|
47 |
|
48 |
/**
|
49 |
* Called after child nodes are visited.
|
50 |
*
|
51 |
+
* @return Node|false The modified node or false if the node must be removed
|
52 |
*/
|
53 |
+
abstract protected function doLeaveNode(Node $node, Environment $env);
|
54 |
}
|
55 |
|
56 |
class_alias('Twig_BaseNodeVisitor', 'Twig\NodeVisitor\AbstractNodeVisitor', false);
|
vendor/twig/twig/lib/Twig/Cache/Filesystem.php
CHANGED
@@ -9,12 +9,14 @@
|
|
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
|
18 |
{
|
19 |
const FORCE_BYTECODE_INVALIDATION = 1;
|
20 |
|
@@ -22,8 +24,8 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface
|
|
22 |
private $options;
|
23 |
|
24 |
/**
|
25 |
-
* @param $directory
|
26 |
-
* @param $options
|
27 |
*/
|
28 |
public function __construct($directory, $options = 0)
|
29 |
{
|
@@ -47,16 +49,16 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface
|
|
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));
|
@@ -65,9 +67,9 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface
|
|
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 |
}
|
@@ -75,7 +77,7 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface
|
|
75 |
return;
|
76 |
}
|
77 |
|
78 |
-
throw new RuntimeException(sprintf('Failed to write cache file "%s".', $key));
|
79 |
}
|
80 |
|
81 |
public function getTimestamp($key)
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Cache\CacheInterface;
|
13 |
+
|
14 |
/**
|
15 |
* Implements a cache on the filesystem.
|
16 |
*
|
17 |
* @author Andrew Tch <andrew@noop.lv>
|
18 |
*/
|
19 |
+
class Twig_Cache_Filesystem implements CacheInterface
|
20 |
{
|
21 |
const FORCE_BYTECODE_INVALIDATION = 1;
|
22 |
|
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 |
{
|
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));
|
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 |
}
|
77 |
return;
|
78 |
}
|
79 |
|
80 |
+
throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $key));
|
81 |
}
|
82 |
|
83 |
public function getTimestamp($key)
|
vendor/twig/twig/lib/Twig/Cache/Null.php
CHANGED
@@ -9,6 +9,8 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
12 |
/**
|
13 |
* Implements a no-cache strategy.
|
14 |
*
|
@@ -16,7 +18,7 @@
|
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
-
class Twig_Cache_Null implements
|
20 |
{
|
21 |
public function generateKey($name, $className)
|
22 |
{
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Cache\CacheInterface;
|
13 |
+
|
14 |
/**
|
15 |
* Implements a no-cache strategy.
|
16 |
*
|
18 |
*
|
19 |
* @author Fabien Potencier <fabien@symfony.com>
|
20 |
*/
|
21 |
+
class Twig_Cache_Null implements CacheInterface
|
22 |
{
|
23 |
public function generateKey($name, $className)
|
24 |
{
|
vendor/twig/twig/lib/Twig/Compiler.php
CHANGED
@@ -10,6 +10,9 @@
|
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
|
|
|
|
|
|
13 |
/**
|
14 |
* Compiles a node to PHP code.
|
15 |
*
|
@@ -27,7 +30,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
27 |
protected $filename;
|
28 |
private $varNameSalt = 0;
|
29 |
|
30 |
-
public function __construct(
|
31 |
{
|
32 |
$this->env = $env;
|
33 |
}
|
@@ -45,7 +48,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
45 |
/**
|
46 |
* Returns the environment instance related to this compiler.
|
47 |
*
|
48 |
-
* @return
|
49 |
*/
|
50 |
public function getEnvironment()
|
51 |
{
|
@@ -65,8 +68,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
65 |
/**
|
66 |
* Compiles a node.
|
67 |
*
|
68 |
-
* @param
|
69 |
-
* @param int $indentation The current indentation
|
70 |
*
|
71 |
* @return $this
|
72 |
*/
|
@@ -81,7 +83,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
81 |
$this->indentation = $indentation;
|
82 |
$this->varNameSalt = 0;
|
83 |
|
84 |
-
if ($node instanceof
|
85 |
// to be removed in 2.0
|
86 |
$this->filename = $node->getTemplateName();
|
87 |
}
|
@@ -123,7 +125,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
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 |
}
|
@@ -170,7 +172,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
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 |
}
|
@@ -182,9 +184,9 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
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) {
|
@@ -225,7 +227,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
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();
|
@@ -262,13 +264,13 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|
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;
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Environment;
|
14 |
+
use Twig\Node\ModuleNode;
|
15 |
+
|
16 |
/**
|
17 |
* Compiles a node to PHP code.
|
18 |
*
|
30 |
protected $filename;
|
31 |
private $varNameSalt = 0;
|
32 |
|
33 |
+
public function __construct(Environment $env)
|
34 |
{
|
35 |
$this->env = $env;
|
36 |
}
|
48 |
/**
|
49 |
* Returns the environment instance related to this compiler.
|
50 |
*
|
51 |
+
* @return Environment
|
52 |
*/
|
53 |
public function getEnvironment()
|
54 |
{
|
68 |
/**
|
69 |
* Compiles a node.
|
70 |
*
|
71 |
+
* @param int $indentation The current indentation
|
|
|
72 |
*
|
73 |
* @return $this
|
74 |
*/
|
83 |
$this->indentation = $indentation;
|
84 |
$this->varNameSalt = 0;
|
85 |
|
86 |
+
if ($node instanceof ModuleNode) {
|
87 |
// to be removed in 2.0
|
88 |
$this->filename = $node->getTemplateName();
|
89 |
}
|
125 |
*/
|
126 |
public function write()
|
127 |
{
|
128 |
+
$strings = \func_get_args();
|
129 |
foreach ($strings as $string) {
|
130 |
$this->source .= str_repeat(' ', $this->indentation * 4).$string;
|
131 |
}
|
172 |
*/
|
173 |
public function repr($value)
|
174 |
{
|
175 |
+
if (\is_int($value) || \is_float($value)) {
|
176 |
if (false !== $locale = setlocale(LC_NUMERIC, '0')) {
|
177 |
setlocale(LC_NUMERIC, 'C');
|
178 |
}
|
184 |
}
|
185 |
} elseif (null === $value) {
|
186 |
$this->raw('null');
|
187 |
+
} elseif (\is_bool($value)) {
|
188 |
$this->raw($value ? 'true' : 'false');
|
189 |
+
} elseif (\is_array($value)) {
|
190 |
$this->raw('[');
|
191 |
$first = true;
|
192 |
foreach ($value as $key => $v) {
|
227 |
} else {
|
228 |
$this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
|
229 |
}
|
230 |
+
$this->sourceOffset = \strlen($this->source);
|
231 |
$this->debugInfo[$this->sourceLine] = $node->getTemplateLine();
|
232 |
|
233 |
$this->lastLine = $node->getTemplateLine();
|
264 |
*
|
265 |
* @return $this
|
266 |
*
|
267 |
+
* @throws \LogicException When trying to outdent too much so the indentation would become negative
|
268 |
*/
|
269 |
public function outdent($step = 1)
|
270 |
{
|
271 |
// can't outdent by more steps than the current indentation level
|
272 |
if ($this->indentation < $step) {
|
273 |
+
throw new \LogicException('Unable to call outdent() as the indentation would become negative.');
|
274 |
}
|
275 |
|
276 |
$this->indentation -= $step;
|
vendor/twig/twig/lib/Twig/ContainerRuntimeLoader.php
CHANGED
@@ -10,6 +10,7 @@
|
|
10 |
*/
|
11 |
|
12 |
use Psr\Container\ContainerInterface;
|
|
|
13 |
|
14 |
/**
|
15 |
* Lazily loads Twig runtime implementations from a PSR-11 container.
|
@@ -19,7 +20,7 @@ use Psr\Container\ContainerInterface;
|
|
19 |
* @author Fabien Potencier <fabien@symfony.com>
|
20 |
* @author Robin Chalas <robin.chalas@gmail.com>
|
21 |
*/
|
22 |
-
class Twig_ContainerRuntimeLoader implements
|
23 |
{
|
24 |
private $container;
|
25 |
|
10 |
*/
|
11 |
|
12 |
use Psr\Container\ContainerInterface;
|
13 |
+
use Twig\RuntimeLoader\RuntimeLoaderInterface;
|
14 |
|
15 |
/**
|
16 |
* Lazily loads Twig runtime implementations from a PSR-11 container.
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
* @author Robin Chalas <robin.chalas@gmail.com>
|
22 |
*/
|
23 |
+
class Twig_ContainerRuntimeLoader implements RuntimeLoaderInterface
|
24 |
{
|
25 |
private $container;
|
26 |
|
vendor/twig/twig/lib/Twig/Environment.php
CHANGED
@@ -9,6 +9,39 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Stores the Twig configuration.
|
14 |
*
|
@@ -16,11 +49,11 @@
|
|
16 |
*/
|
17 |
class Twig_Environment
|
18 |
{
|
19 |
-
const VERSION = '1.
|
20 |
-
const VERSION_ID =
|
21 |
const MAJOR_VERSION = 1;
|
22 |
-
const MINOR_VERSION =
|
23 |
-
const RELEASE_VERSION =
|
24 |
const EXTRA_VERSION = 'DEV';
|
25 |
|
26 |
protected $charset;
|
@@ -94,22 +127,19 @@ class Twig_Environment
|
|
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(
|
102 |
{
|
103 |
if (null !== $loader) {
|
104 |
$this->setLoader($loader);
|
105 |
} else {
|
106 |
-
@trigger_error('Not passing a
|
107 |
}
|
108 |
|
109 |
$options = array_merge([
|
110 |
'debug' => false,
|
111 |
'charset' => 'UTF-8',
|
112 |
-
'base_template_class' => '
|
113 |
'strict_variables' => false,
|
114 |
'autoescape' => 'html',
|
115 |
'cache' => false,
|
@@ -124,23 +154,23 @@ class Twig_Environment
|
|
124 |
$this->strictVariables = (bool) $options['strict_variables'];
|
125 |
$this->setCache($options['cache']);
|
126 |
|
127 |
-
$this->addExtension(new
|
128 |
-
$this->addExtension(new
|
129 |
-
$this->addExtension(new
|
130 |
-
$this->staging = new
|
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
|
137 |
|
138 |
$this->bcWriteCacheFile = true;
|
139 |
}
|
140 |
|
141 |
-
$r = new ReflectionMethod($this, 'getCacheFilename');
|
142 |
if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
|
143 |
-
@trigger_error('The
|
144 |
|
145 |
$this->bcGetCacheFilename = true;
|
146 |
}
|
@@ -255,9 +285,9 @@ class Twig_Environment
|
|
255 |
*
|
256 |
* @param bool $original Whether to return the original cache option or the real cache instance
|
257 |
*
|
258 |
-
* @return
|
259 |
-
*
|
260 |
-
*
|
261 |
*/
|
262 |
public function getCache($original = true)
|
263 |
{
|
@@ -267,26 +297,26 @@ class Twig_Environment
|
|
267 |
/**
|
268 |
* Sets the current cache implementation.
|
269 |
*
|
270 |
-
* @param
|
271 |
-
*
|
272 |
-
*
|
273 |
*/
|
274 |
public function setCache($cache)
|
275 |
{
|
276 |
-
if (is_string($cache)) {
|
277 |
$this->originalCache = $cache;
|
278 |
-
$this->cache = new
|
279 |
} elseif (false === $cache) {
|
280 |
$this->originalCache = $cache;
|
281 |
-
$this->cache = new
|
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
|
286 |
-
} elseif ($cache instanceof
|
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 |
|
@@ -354,9 +384,9 @@ class Twig_Environment
|
|
354 |
*
|
355 |
* @return string The rendered template
|
356 |
*
|
357 |
-
* @throws
|
358 |
-
* @throws
|
359 |
-
* @throws
|
360 |
*/
|
361 |
public function render($name, array $context = [])
|
362 |
{
|
@@ -369,9 +399,9 @@ class Twig_Environment
|
|
369 |
* @param string $name The template name
|
370 |
* @param array $context An array of parameters to pass to the template
|
371 |
*
|
372 |
-
* @throws
|
373 |
-
* @throws
|
374 |
-
* @throws
|
375 |
*/
|
376 |
public function display($name, array $context = [])
|
377 |
{
|
@@ -381,25 +411,25 @@ class Twig_Environment
|
|
381 |
/**
|
382 |
* Loads a template.
|
383 |
*
|
384 |
-
* @param string|
|
385 |
*
|
386 |
-
* @throws
|
387 |
-
* @throws
|
388 |
-
* @throws
|
389 |
*
|
390 |
-
* @return
|
391 |
*/
|
392 |
public function load($name)
|
393 |
{
|
394 |
-
if ($name instanceof
|
395 |
return $name;
|
396 |
}
|
397 |
|
398 |
-
if ($name instanceof
|
399 |
-
return new
|
400 |
}
|
401 |
|
402 |
-
return new
|
403 |
}
|
404 |
|
405 |
/**
|
@@ -413,9 +443,9 @@ class Twig_Environment
|
|
413 |
*
|
414 |
* @return Twig_TemplateInterface A template instance representing the given template name
|
415 |
*
|
416 |
-
* @throws
|
417 |
-
* @throws
|
418 |
-
* @throws
|
419 |
*
|
420 |
* @internal
|
421 |
*/
|
@@ -443,8 +473,8 @@ class Twig_Environment
|
|
443 |
|
444 |
if (!class_exists($cls, false)) {
|
445 |
$loader = $this->getLoader();
|
446 |
-
if (!$loader instanceof
|
447 |
-
$source = new
|
448 |
} else {
|
449 |
$source = $loader->getSourceContext($name);
|
450 |
}
|
@@ -469,7 +499,7 @@ class Twig_Environment
|
|
469 |
}
|
470 |
|
471 |
if (!class_exists($cls, false)) {
|
472 |
-
throw new
|
473 |
}
|
474 |
}
|
475 |
|
@@ -478,7 +508,7 @@ class Twig_Environment
|
|
478 |
}
|
479 |
|
480 |
if (isset($this->loading[$cls])) {
|
481 |
-
throw new
|
482 |
}
|
483 |
|
484 |
$this->loading[$cls] = $name;
|
@@ -502,28 +532,28 @@ class Twig_Environment
|
|
502 |
*
|
503 |
* @param string $template The template name
|
504 |
*
|
505 |
-
* @return
|
506 |
*
|
507 |
-
* @throws
|
508 |
-
* @throws
|
509 |
*/
|
510 |
public function createTemplate($template)
|
511 |
{
|
512 |
$name = sprintf('__string_template__%s', hash('sha256', $template, false));
|
513 |
|
514 |
-
$loader = new
|
515 |
-
new
|
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;
|
@@ -549,7 +579,7 @@ class Twig_Environment
|
|
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 |
}
|
@@ -565,39 +595,38 @@ class Twig_Environment
|
|
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|
|
569 |
*
|
570 |
-
* @return
|
571 |
*
|
572 |
-
* @throws
|
573 |
-
* @throws
|
574 |
*/
|
575 |
public function resolveTemplate($names)
|
576 |
{
|
577 |
-
if (
|
578 |
$names = [$names];
|
579 |
}
|
580 |
|
581 |
foreach ($names as $name) {
|
582 |
-
if ($name instanceof
|
583 |
return $name;
|
584 |
}
|
585 |
|
586 |
-
if ($name instanceof
|
587 |
return $name;
|
588 |
}
|
589 |
|
590 |
try {
|
591 |
return $this->loadTemplate($name);
|
592 |
-
} catch (
|
|
|
|
|
|
|
593 |
}
|
594 |
}
|
595 |
|
596 |
-
|
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 |
/**
|
@@ -621,8 +650,8 @@ class Twig_Environment
|
|
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 |
}
|
@@ -642,7 +671,7 @@ class Twig_Environment
|
|
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
|
646 |
}
|
647 |
|
648 |
return $this->lexer;
|
@@ -656,22 +685,22 @@ class Twig_Environment
|
|
656 |
/**
|
657 |
* Tokenizes a source code.
|
658 |
*
|
659 |
-
* @param string|
|
660 |
-
* @param string
|
661 |
*
|
662 |
-
* @return
|
663 |
*
|
664 |
-
* @throws
|
665 |
*/
|
666 |
public function tokenize($source, $name = null)
|
667 |
{
|
668 |
-
if (!$source instanceof
|
669 |
-
@trigger_error(sprintf('Passing a string as the $source argument of %s() is deprecated since version 1.27. Pass a
|
670 |
-
$source = new
|
671 |
}
|
672 |
|
673 |
if (null === $this->lexer) {
|
674 |
-
$this->lexer = new
|
675 |
}
|
676 |
|
677 |
return $this->lexer->tokenize($source);
|
@@ -689,7 +718,7 @@ class Twig_Environment
|
|
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
|
693 |
}
|
694 |
|
695 |
return $this->parser;
|
@@ -703,14 +732,14 @@ class Twig_Environment
|
|
703 |
/**
|
704 |
* Converts a token stream to a node tree.
|
705 |
*
|
706 |
-
* @return
|
707 |
*
|
708 |
-
* @throws
|
709 |
*/
|
710 |
-
public function parse(
|
711 |
{
|
712 |
if (null === $this->parser) {
|
713 |
-
$this->parser = new
|
714 |
}
|
715 |
|
716 |
return $this->parser->parse($stream);
|
@@ -728,7 +757,7 @@ class Twig_Environment
|
|
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
|
732 |
}
|
733 |
|
734 |
return $this->compiler;
|
@@ -747,7 +776,7 @@ class Twig_Environment
|
|
747 |
public function compile(Twig_NodeInterface $node)
|
748 |
{
|
749 |
if (null === $this->compiler) {
|
750 |
-
$this->compiler = new
|
751 |
}
|
752 |
|
753 |
return $this->compiler->compile($node)->getSource();
|
@@ -756,34 +785,34 @@ class Twig_Environment
|
|
756 |
/**
|
757 |
* Compiles a template source code.
|
758 |
*
|
759 |
-
* @param string|
|
760 |
-
* @param string
|
761 |
*
|
762 |
* @return string The compiled PHP source code
|
763 |
*
|
764 |
-
* @throws
|
765 |
*/
|
766 |
public function compileSource($source, $name = null)
|
767 |
{
|
768 |
-
if (!$source instanceof
|
769 |
-
@trigger_error(sprintf('Passing a string as the $source argument of %s() is deprecated since version 1.27. Pass a
|
770 |
-
$source = new
|
771 |
}
|
772 |
|
773 |
try {
|
774 |
return $this->compile($this->parse($this->tokenize($source)));
|
775 |
-
} catch (
|
776 |
$e->setSourceContext($source);
|
777 |
throw $e;
|
778 |
-
} catch (Exception $e) {
|
779 |
-
throw new
|
780 |
}
|
781 |
}
|
782 |
|
783 |
-
public function setLoader(
|
784 |
{
|
785 |
-
if (!$loader instanceof
|
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;
|
@@ -792,12 +821,12 @@ class Twig_Environment
|
|
792 |
/**
|
793 |
* Gets the Loader instance.
|
794 |
*
|
795 |
-
* @return
|
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;
|
@@ -833,11 +862,11 @@ class Twig_Environment
|
|
833 |
$this->runtimeInitialized = true;
|
834 |
|
835 |
foreach ($this->getExtensions() as $name => $extension) {
|
836 |
-
if (!$extension instanceof
|
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
|
841 |
}
|
842 |
}
|
843 |
|
@@ -857,12 +886,12 @@ class Twig_Environment
|
|
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 |
|
@@ -875,7 +904,7 @@ class Twig_Environment
|
|
875 |
/**
|
876 |
* Adds a runtime loader.
|
877 |
*/
|
878 |
-
public function addRuntimeLoader(
|
879 |
{
|
880 |
$this->runtimeLoaders[] = $loader;
|
881 |
}
|
@@ -885,19 +914,19 @@ class Twig_Environment
|
|
885 |
*
|
886 |
* @param string $class The extension class name
|
887 |
*
|
888 |
-
* @return
|
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 |
|
@@ -905,7 +934,7 @@ class Twig_Environment
|
|
905 |
}
|
906 |
|
907 |
if (!isset($this->extensionsByClass[$class])) {
|
908 |
-
throw new
|
909 |
}
|
910 |
|
911 |
return $this->extensionsByClass[$class];
|
@@ -918,7 +947,7 @@ class Twig_Environment
|
|
918 |
*
|
919 |
* @return object The runtime implementation
|
920 |
*
|
921 |
-
* @throws
|
922 |
*/
|
923 |
public function getRuntime($class)
|
924 |
{
|
@@ -932,16 +961,16 @@ class Twig_Environment
|
|
932 |
}
|
933 |
}
|
934 |
|
935 |
-
throw new
|
936 |
}
|
937 |
|
938 |
-
public function addExtension(
|
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]);
|
@@ -969,18 +998,18 @@ class Twig_Environment
|
|
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 |
|
@@ -1006,17 +1035,17 @@ class Twig_Environment
|
|
1006 |
/**
|
1007 |
* Returns all registered extensions.
|
1008 |
*
|
1009 |
-
* @return
|
1010 |
*/
|
1011 |
public function getExtensions()
|
1012 |
{
|
1013 |
return $this->extensions;
|
1014 |
}
|
1015 |
|
1016 |
-
public function addTokenParser(
|
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);
|
@@ -1043,7 +1072,7 @@ class Twig_Environment
|
|
1043 |
*
|
1044 |
* Be warned that this method cannot return tags defined by Twig_TokenParserBrokerInterface classes.
|
1045 |
*
|
1046 |
-
* @return
|
1047 |
*
|
1048 |
* @internal
|
1049 |
*/
|
@@ -1051,7 +1080,7 @@ class Twig_Environment
|
|
1051 |
{
|
1052 |
$tags = [];
|
1053 |
foreach ($this->getTokenParsers()->getParsers() as $parser) {
|
1054 |
-
if ($parser instanceof
|
1055 |
$tags[$parser->getTag()] = $parser;
|
1056 |
}
|
1057 |
}
|
@@ -1059,10 +1088,10 @@ class Twig_Environment
|
|
1059 |
return $tags;
|
1060 |
}
|
1061 |
|
1062 |
-
public function addNodeVisitor(
|
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);
|
@@ -1071,7 +1100,7 @@ class Twig_Environment
|
|
1071 |
/**
|
1072 |
* Gets the registered Node Visitors.
|
1073 |
*
|
1074 |
-
* @return
|
1075 |
*
|
1076 |
* @internal
|
1077 |
*/
|
@@ -1087,16 +1116,16 @@ class Twig_Environment
|
|
1087 |
/**
|
1088 |
* Registers a Filter.
|
1089 |
*
|
1090 |
-
* @param string|
|
1091 |
-
* @param Twig_FilterInterface|
|
1092 |
*/
|
1093 |
public function addFilter($name, $filter = null)
|
1094 |
{
|
1095 |
-
if (!$name instanceof
|
1096 |
-
throw new LogicException('A filter must be an instance of Twig_FilterInterface or Twig_SimpleFilter.');
|
1097 |
}
|
1098 |
|
1099 |
-
if ($name instanceof
|
1100 |
$filter = $name;
|
1101 |
$name = $filter->getName();
|
1102 |
} else {
|
@@ -1104,7 +1133,7 @@ class Twig_Environment
|
|
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);
|
@@ -1146,7 +1175,7 @@ class Twig_Environment
|
|
1146 |
}
|
1147 |
|
1148 |
foreach ($this->filterCallbacks as $callback) {
|
1149 |
-
if (false !== $filter = call_user_func($callback, $name)) {
|
1150 |
return $filter;
|
1151 |
}
|
1152 |
}
|
@@ -1182,16 +1211,16 @@ class Twig_Environment
|
|
1182 |
/**
|
1183 |
* Registers a Test.
|
1184 |
*
|
1185 |
-
* @param string|
|
1186 |
-
* @param Twig_TestInterface|
|
1187 |
*/
|
1188 |
public function addTest($name, $test = null)
|
1189 |
{
|
1190 |
-
if (!$name instanceof
|
1191 |
-
throw new LogicException('A test must be an instance of Twig_TestInterface or Twig_SimpleTest.');
|
1192 |
}
|
1193 |
|
1194 |
-
if ($name instanceof
|
1195 |
$test = $name;
|
1196 |
$name = $test->getName();
|
1197 |
} else {
|
@@ -1199,7 +1228,7 @@ class Twig_Environment
|
|
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);
|
@@ -1259,16 +1288,16 @@ class Twig_Environment
|
|
1259 |
/**
|
1260 |
* Registers a Function.
|
1261 |
*
|
1262 |
-
* @param string|
|
1263 |
-
* @param Twig_FunctionInterface|
|
1264 |
*/
|
1265 |
public function addFunction($name, $function = null)
|
1266 |
{
|
1267 |
-
if (!$name instanceof
|
1268 |
-
throw new LogicException('A function must be an instance of Twig_FunctionInterface or Twig_SimpleFunction.');
|
1269 |
}
|
1270 |
|
1271 |
-
if ($name instanceof
|
1272 |
$function = $name;
|
1273 |
$name = $function->getName();
|
1274 |
} else {
|
@@ -1276,7 +1305,7 @@ class Twig_Environment
|
|
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);
|
@@ -1318,7 +1347,7 @@ class Twig_Environment
|
|
1318 |
}
|
1319 |
|
1320 |
foreach ($this->functionCallbacks as $callback) {
|
1321 |
-
if (false !== $function = call_user_func($callback, $name)) {
|
1322 |
return $function;
|
1323 |
}
|
1324 |
}
|
@@ -1367,10 +1396,10 @@ class Twig_Environment
|
|
1367 |
$this->globals = $this->initGlobals();
|
1368 |
}
|
1369 |
|
1370 |
-
if (
|
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 |
|
@@ -1414,7 +1443,7 @@ class Twig_Environment
|
|
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 (
|
1418 |
$context[$key] = $value;
|
1419 |
}
|
1420 |
}
|
@@ -1461,7 +1490,7 @@ class Twig_Environment
|
|
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
|
1465 |
}
|
1466 |
|
1467 |
/**
|
@@ -1471,17 +1500,17 @@ class Twig_Environment
|
|
1471 |
{
|
1472 |
$globals = [];
|
1473 |
foreach ($this->extensions as $name => $extension) {
|
1474 |
-
if (!$extension instanceof
|
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
|
1479 |
}
|
1480 |
}
|
1481 |
|
1482 |
$extGlob = $extension->getGlobals();
|
1483 |
-
if (
|
1484 |
-
throw new UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', get_class($extension)));
|
1485 |
}
|
1486 |
|
1487 |
$globals[] = $extGlob;
|
@@ -1489,7 +1518,7 @@ class Twig_Environment
|
|
1489 |
|
1490 |
$globals[] = $this->staging->getGlobals();
|
1491 |
|
1492 |
-
return call_user_func_array('array_merge', $globals);
|
1493 |
}
|
1494 |
|
1495 |
/**
|
@@ -1520,14 +1549,14 @@ class Twig_Environment
|
|
1520 |
/**
|
1521 |
* @internal
|
1522 |
*/
|
1523 |
-
protected function initExtension(
|
1524 |
{
|
1525 |
// filters
|
1526 |
foreach ($extension->getFilters() as $name => $filter) {
|
1527 |
-
if ($filter instanceof
|
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;
|
@@ -1535,10 +1564,10 @@ class Twig_Environment
|
|
1535 |
|
1536 |
// functions
|
1537 |
foreach ($extension->getFunctions() as $name => $function) {
|
1538 |
-
if ($function instanceof
|
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;
|
@@ -1546,10 +1575,10 @@ class Twig_Environment
|
|
1546 |
|
1547 |
// tests
|
1548 |
foreach ($extension->getTests() as $name => $test) {
|
1549 |
-
if ($test instanceof
|
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;
|
@@ -1557,14 +1586,14 @@ class Twig_Environment
|
|
1557 |
|
1558 |
// token parsers
|
1559 |
foreach ($extension->getTokenParsers() as $parser) {
|
1560 |
-
if ($parser instanceof
|
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 |
|
@@ -1575,12 +1604,12 @@ class Twig_Environment
|
|
1575 |
|
1576 |
// operators
|
1577 |
if ($operators = $extension->getOperators()) {
|
1578 |
-
if (
|
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]);
|
@@ -1601,7 +1630,7 @@ class Twig_Environment
|
|
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,
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Cache\CacheInterface;
|
13 |
+
use Twig\Cache\FilesystemCache;
|
14 |
+
use Twig\Cache\NullCache;
|
15 |
+
use Twig\Compiler;
|
16 |
+
use Twig\Error\Error;
|
17 |
+
use Twig\Error\LoaderError;
|
18 |
+
use Twig\Error\RuntimeError;
|
19 |
+
use Twig\Error\SyntaxError;
|
20 |
+
use Twig\Extension\CoreExtension;
|
21 |
+
use Twig\Extension\EscaperExtension;
|
22 |
+
use Twig\Extension\ExtensionInterface;
|
23 |
+
use Twig\Extension\GlobalsInterface;
|
24 |
+
use Twig\Extension\InitRuntimeInterface;
|
25 |
+
use Twig\Extension\OptimizerExtension;
|
26 |
+
use Twig\Extension\StagingExtension;
|
27 |
+
use Twig\Lexer;
|
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\Parser;
|
35 |
+
use Twig\RuntimeLoader\RuntimeLoaderInterface;
|
36 |
+
use Twig\Source;
|
37 |
+
use Twig\Template;
|
38 |
+
use Twig\TemplateWrapper;
|
39 |
+
use Twig\TokenParser\TokenParserInterface;
|
40 |
+
use Twig\TokenStream;
|
41 |
+
use Twig\TwigFilter;
|
42 |
+
use Twig\TwigFunction;
|
43 |
+
use Twig\TwigTest;
|
44 |
+
|
45 |
/**
|
46 |
* Stores the Twig configuration.
|
47 |
*
|
49 |
*/
|
50 |
class Twig_Environment
|
51 |
{
|
52 |
+
const VERSION = '1.38.0-DEV';
|
53 |
+
const VERSION_ID = 13800;
|
54 |
const MAJOR_VERSION = 1;
|
55 |
+
const MINOR_VERSION = 38;
|
56 |
+
const RELEASE_VERSION = 0;
|
57 |
const EXTRA_VERSION = 'DEV';
|
58 |
|
59 |
protected $charset;
|
127 |
* * optimizations: A flag that indicates which optimizations to apply
|
128 |
* (default to -1 which means that all optimizations are enabled;
|
129 |
* set it to 0 to disable).
|
|
|
|
|
|
|
130 |
*/
|
131 |
+
public function __construct(LoaderInterface $loader = null, $options = [])
|
132 |
{
|
133 |
if (null !== $loader) {
|
134 |
$this->setLoader($loader);
|
135 |
} else {
|
136 |
+
@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);
|
137 |
}
|
138 |
|
139 |
$options = array_merge([
|
140 |
'debug' => false,
|
141 |
'charset' => 'UTF-8',
|
142 |
+
'base_template_class' => '\Twig\Template',
|
143 |
'strict_variables' => false,
|
144 |
'autoescape' => 'html',
|
145 |
'cache' => false,
|
154 |
$this->strictVariables = (bool) $options['strict_variables'];
|
155 |
$this->setCache($options['cache']);
|
156 |
|
157 |
+
$this->addExtension(new CoreExtension());
|
158 |
+
$this->addExtension(new EscaperExtension($options['autoescape']));
|
159 |
+
$this->addExtension(new OptimizerExtension($options['optimizations']));
|
160 |
+
$this->staging = new StagingExtension();
|
161 |
|
162 |
// For BC
|
163 |
+
if (\is_string($this->originalCache)) {
|
164 |
+
$r = new \ReflectionMethod($this, 'writeCacheFile');
|
165 |
if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
|
166 |
+
@trigger_error('The Twig\Environment::writeCacheFile method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED);
|
167 |
|
168 |
$this->bcWriteCacheFile = true;
|
169 |
}
|
170 |
|
171 |
+
$r = new \ReflectionMethod($this, 'getCacheFilename');
|
172 |
if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
|
173 |
+
@trigger_error('The Twig\Environment::getCacheFilename method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED);
|
174 |
|
175 |
$this->bcGetCacheFilename = true;
|
176 |
}
|
285 |
*
|
286 |
* @param bool $original Whether to return the original cache option or the real cache instance
|
287 |
*
|
288 |
+
* @return CacheInterface|string|false A Twig_CacheInterface implementation,
|
289 |
+
* an absolute path to the compiled templates,
|
290 |
+
* or false to disable cache
|
291 |
*/
|
292 |
public function getCache($original = true)
|
293 |
{
|
297 |
/**
|
298 |
* Sets the current cache implementation.
|
299 |
*
|
300 |
+
* @param CacheInterface|string|false $cache A Twig_CacheInterface implementation,
|
301 |
+
* an absolute path to the compiled templates,
|
302 |
+
* or false to disable cache
|
303 |
*/
|
304 |
public function setCache($cache)
|
305 |
{
|
306 |
+
if (\is_string($cache)) {
|
307 |
$this->originalCache = $cache;
|
308 |
+
$this->cache = new FilesystemCache($cache);
|
309 |
} elseif (false === $cache) {
|
310 |
$this->originalCache = $cache;
|
311 |
+
$this->cache = new NullCache();
|
312 |
} elseif (null === $cache) {
|
313 |
@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);
|
314 |
$this->originalCache = false;
|
315 |
+
$this->cache = new NullCache();
|
316 |
+
} elseif ($cache instanceof CacheInterface) {
|
317 |
$this->originalCache = $this->cache = $cache;
|
318 |
} else {
|
319 |
+
throw new \LogicException(sprintf('Cache can only be a string, false, or a Twig_CacheInterface implementation.'));
|
320 |
}
|
321 |
}
|
322 |
|
384 |
*
|
385 |
* @return string The rendered template
|
386 |
*
|
387 |
+
* @throws LoaderError When the template cannot be found
|
388 |
+
* @throws SyntaxError When an error occurred during compilation
|
389 |
+
* @throws RuntimeError When an error occurred during rendering
|
390 |
*/
|
391 |
public function render($name, array $context = [])
|
392 |
{
|
399 |
* @param string $name The template name
|
400 |
* @param array $context An array of parameters to pass to the template
|
401 |
*
|
402 |
+
* @throws LoaderError When the template cannot be found
|
403 |
+
* @throws SyntaxError When an error occurred during compilation
|
404 |
+
* @throws RuntimeError When an error occurred during rendering
|
405 |
*/
|
406 |
public function display($name, array $context = [])
|
407 |
{
|
411 |
/**
|
412 |
* Loads a template.
|
413 |
*
|
414 |
+
* @param string|TemplateWrapper|\Twig\Template $name The template name
|
415 |
*
|
416 |
+
* @throws LoaderError When the template cannot be found
|
417 |
+
* @throws RuntimeError When a previously generated cache is corrupted
|
418 |
+
* @throws SyntaxError When an error occurred during compilation
|
419 |
*
|
420 |
+
* @return TemplateWrapper
|
421 |
*/
|
422 |
public function load($name)
|
423 |
{
|
424 |
+
if ($name instanceof TemplateWrapper) {
|
425 |
return $name;
|
426 |
}
|
427 |
|
428 |
+
if ($name instanceof Template) {
|
429 |
+
return new TemplateWrapper($this, $name);
|
430 |
}
|
431 |
|
432 |
+
return new TemplateWrapper($this, $this->loadTemplate($name));
|
433 |
}
|
434 |
|
435 |
/**
|
443 |
*
|
444 |
* @return Twig_TemplateInterface A template instance representing the given template name
|
445 |
*
|
446 |
+
* @throws LoaderError When the template cannot be found
|
447 |
+
* @throws RuntimeError When a previously generated cache is corrupted
|
448 |
+
* @throws SyntaxError When an error occurred during compilation
|
449 |
*
|
450 |
* @internal
|
451 |
*/
|
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 |
}
|
499 |
}
|
500 |
|
501 |
if (!class_exists($cls, false)) {
|
502 |
+
throw new RuntimeError(sprintf('Failed to load Twig template "%s", index "%s": cache is corrupted.', $name, $index), -1, $source);
|
503 |
}
|
504 |
}
|
505 |
|
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;
|
532 |
*
|
533 |
* @param string $template The template name
|
534 |
*
|
535 |
+
* @return Template 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 = $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;
|
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 |
}
|
595 |
* Similar to loadTemplate() 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 Template|Twig_TemplateWrapper
|
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 |
|
616 |
+
if ($name instanceof TemplateWrapper) {
|
617 |
return $name;
|
618 |
}
|
619 |
|
620 |
try {
|
621 |
return $this->loadTemplate($name);
|
622 |
+
} catch (LoaderError $e) {
|
623 |
+
if (1 === \count($names)) {
|
624 |
+
throw $e;
|
625 |
+
}
|
626 |
}
|
627 |
}
|
628 |
|
629 |
+
throw new LoaderError(sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names)));
|
|
|
|
|
|
|
|
|
630 |
}
|
631 |
|
632 |
/**
|
650 |
{
|
651 |
@trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
652 |
|
653 |
+
if (\is_string($this->originalCache)) {
|
654 |
+
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->originalCache), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
|
655 |
if ($file->isFile()) {
|
656 |
@unlink($file->getPathname());
|
657 |
}
|
671 |
@trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED);
|
672 |
|
673 |
if (null === $this->lexer) {
|
674 |
+
$this->lexer = new Lexer($this);
|
675 |
}
|
676 |
|
677 |
return $this->lexer;
|
685 |
/**
|
686 |
* Tokenizes a source code.
|
687 |
*
|
688 |
+
* @param string|Source $source The template source code
|
689 |
+
* @param string $name The template name (deprecated)
|
690 |
*
|
691 |
+
* @return TokenStream
|
692 |
*
|
693 |
+
* @throws SyntaxError When the code is syntactically wrong
|
694 |
*/
|
695 |
public function tokenize($source, $name = null)
|
696 |
{
|
697 |
+
if (!$source instanceof Source) {
|
698 |
+
@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);
|
699 |
+
$source = new Source($source, $name);
|
700 |
}
|
701 |
|
702 |
if (null === $this->lexer) {
|
703 |
+
$this->lexer = new Lexer($this);
|
704 |
}
|
705 |
|
706 |
return $this->lexer->tokenize($source);
|
718 |
@trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED);
|
719 |
|
720 |
if (null === $this->parser) {
|
721 |
+
$this->parser = new Parser($this);
|
722 |
}
|
723 |
|
724 |
return $this->parser;
|
732 |
/**
|
733 |
* Converts a token stream to a node tree.
|
734 |
*
|
735 |
+
* @return ModuleNode
|
736 |
*
|
737 |
+
* @throws SyntaxError When the token stream is syntactically or semantically wrong
|
738 |
*/
|
739 |
+
public function parse(TokenStream $stream)
|
740 |
{
|
741 |
if (null === $this->parser) {
|
742 |
+
$this->parser = new Parser($this);
|
743 |
}
|
744 |
|
745 |
return $this->parser->parse($stream);
|
757 |
@trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED);
|
758 |
|
759 |
if (null === $this->compiler) {
|
760 |
+
$this->compiler = new Compiler($this);
|
761 |
}
|
762 |
|
763 |
return $this->compiler;
|
776 |
public function compile(Twig_NodeInterface $node)
|
777 |
{
|
778 |
if (null === $this->compiler) {
|
779 |
+
$this->compiler = new Compiler($this);
|
780 |
}
|
781 |
|
782 |
return $this->compiler->compile($node)->getSource();
|
785 |
/**
|
786 |
* Compiles a template source code.
|
787 |
*
|
788 |
+
* @param string|Source $source The template source code
|
789 |
+
* @param string $name The template name (deprecated)
|
790 |
*
|
791 |
* @return string The compiled PHP source code
|
792 |
*
|
793 |
+
* @throws SyntaxError When there was an error during tokenizing, parsing or compiling
|
794 |
*/
|
795 |
public function compileSource($source, $name = null)
|
796 |
{
|
797 |
+
if (!$source instanceof Source) {
|
798 |
+
@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);
|
799 |
+
$source = new Source($source, $name);
|
800 |
}
|
801 |
|
802 |
try {
|
803 |
return $this->compile($this->parse($this->tokenize($source)));
|
804 |
+
} catch (Error $e) {
|
805 |
$e->setSourceContext($source);
|
806 |
throw $e;
|
807 |
+
} catch (\Exception $e) {
|
808 |
+
throw new SyntaxError(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $source, $e);
|
809 |
}
|
810 |
}
|
811 |
|
812 |
+
public function setLoader(LoaderInterface $loader)
|
813 |
{
|
814 |
+
if (!$loader instanceof SourceContextLoaderInterface && 0 !== strpos(\get_class($loader), 'Mock_')) {
|
815 |
+
@trigger_error(sprintf('Twig loader "%s" should implement Twig_SourceContextLoaderInterface since version 1.27.', \get_class($loader)), E_USER_DEPRECATED);
|
816 |
}
|
817 |
|
818 |
$this->loader = $loader;
|
821 |
/**
|
822 |
* Gets the Loader instance.
|
823 |
*
|
824 |
+
* @return LoaderInterface
|
825 |
*/
|
826 |
public function getLoader()
|
827 |
{
|
828 |
if (null === $this->loader) {
|
829 |
+
throw new \LogicException('You must set a loader first.');
|
830 |
}
|
831 |
|
832 |
return $this->loader;
|
862 |
$this->runtimeInitialized = true;
|
863 |
|
864 |
foreach ($this->getExtensions() as $name => $extension) {
|
865 |
+
if (!$extension instanceof InitRuntimeInterface) {
|
866 |
+
$m = new \ReflectionMethod($extension, 'initRuntime');
|
867 |
|
868 |
if ('Twig_Extension' !== $m->getDeclaringClass()->getName()) {
|
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 |
|
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 |
|
904 |
/**
|
905 |
* Adds a runtime loader.
|
906 |
*/
|
907 |
+
public function addRuntimeLoader(RuntimeLoaderInterface $loader)
|
908 |
{
|
909 |
$this->runtimeLoaders[] = $loader;
|
910 |
}
|
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 |
|
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];
|
947 |
*
|
948 |
* @return object The runtime implementation
|
949 |
*
|
950 |
+
* @throws RuntimeError When the template cannot be found
|
951 |
*/
|
952 |
public function getRuntime($class)
|
953 |
{
|
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]);
|
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 |
|
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);
|
1072 |
*
|
1073 |
* Be warned that this method cannot return tags defined by Twig_TokenParserBrokerInterface classes.
|
1074 |
*
|
1075 |
+
* @return TokenParserInterface[]
|
1076 |
*
|
1077 |
* @internal
|
1078 |
*/
|
1080 |
{
|
1081 |
$tags = [];
|
1082 |
foreach ($this->getTokenParsers()->getParsers() as $parser) {
|
1083 |
+
if ($parser instanceof TokenParserInterface) {
|
1084 |
$tags[$parser->getTag()] = $parser;
|
1085 |
}
|
1086 |
}
|
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);
|
1100 |
/**
|
1101 |
* Gets the registered Node Visitors.
|
1102 |
*
|
1103 |
+
* @return NodeVisitorInterface[]
|
1104 |
*
|
1105 |
* @internal
|
1106 |
*/
|
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 {
|
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);
|
1175 |
}
|
1176 |
|
1177 |
foreach ($this->filterCallbacks as $callback) {
|
1178 |
+
if (false !== $filter = \call_user_func($callback, $name)) {
|
1179 |
return $filter;
|
1180 |
}
|
1181 |
}
|
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 {
|
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);
|
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 {
|
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);
|
1347 |
}
|
1348 |
|
1349 |
foreach ($this->functionCallbacks as $callback) {
|
1350 |
+
if (false !== $function = \call_user_func($callback, $name)) {
|
1351 |
return $function;
|
1352 |
}
|
1353 |
}
|
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 |
|
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 |
}
|
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 |
/**
|
1500 |
{
|
1501 |
$globals = [];
|
1502 |
foreach ($this->extensions as $name => $extension) {
|
1503 |
+
if (!$extension instanceof GlobalsInterface) {
|
1504 |
+
$m = new \ReflectionMethod($extension, 'getGlobals');
|
1505 |
|
1506 |
if ('Twig_Extension' !== $m->getDeclaringClass()->getName()) {
|
1507 |
+
@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);
|
1508 |
}
|
1509 |
}
|
1510 |
|
1511 |
$extGlob = $extension->getGlobals();
|
1512 |
+
if (!\is_array($extGlob)) {
|
1513 |
+
throw new \UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', \get_class($extension)));
|
1514 |
}
|
1515 |
|
1516 |
$globals[] = $extGlob;
|
1518 |
|
1519 |
$globals[] = $this->staging->getGlobals();
|
1520 |
|
1521 |
+
return \call_user_func_array('array_merge', $globals);
|
1522 |
}
|
1523 |
|
1524 |
/**
|
1549 |
/**
|
1550 |
* @internal
|
1551 |
*/
|
1552 |
+
protected function initExtension(ExtensionInterface $extension)
|
1553 |
{
|
1554 |
// filters
|
1555 |
foreach ($extension->getFilters() as $name => $filter) {
|
1556 |
+
if ($filter instanceof TwigFilter) {
|
1557 |
$name = $filter->getName();
|
1558 |
} else {
|
1559 |
+
@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);
|
1560 |
}
|
1561 |
|
1562 |
$this->filters[$name] = $filter;
|
1564 |
|
1565 |
// functions
|
1566 |
foreach ($extension->getFunctions() as $name => $function) {
|
1567 |
+
if ($function instanceof TwigFunction) {
|
1568 |
$name = $function->getName();
|
1569 |
} else {
|
1570 |
+
@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);
|
1571 |
}
|
1572 |
|
1573 |
$this->functions[$name] = $function;
|
1575 |
|
1576 |
// tests
|
1577 |
foreach ($extension->getTests() as $name => $test) {
|
1578 |
+
if ($test instanceof TwigTest) {
|
1579 |
$name = $test->getName();
|
1580 |
} else {
|
1581 |
+
@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);
|
1582 |
}
|
1583 |
|
1584 |
$this->tests[$name] = $test;
|
1586 |
|
1587 |
// token parsers
|
1588 |
foreach ($extension->getTokenParsers() as $parser) {
|
1589 |
+
if ($parser instanceof TokenParserInterface) {
|
1590 |
$this->parsers->addTokenParser($parser);
|
1591 |
} elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
|
1592 |
@trigger_error('Registering a Twig_TokenParserBrokerInterface instance is deprecated since version 1.21.', E_USER_DEPRECATED);
|
1593 |
|
1594 |
$this->parsers->addTokenParserBroker($parser);
|
1595 |
} else {
|
1596 |
+
throw new \LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances.');
|
1597 |
}
|
1598 |
}
|
1599 |
|
1604 |
|
1605 |
// operators
|
1606 |
if ($operators = $extension->getOperators()) {
|
1607 |
+
if (!\is_array($operators)) {
|
1608 |
+
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)));
|
1609 |
}
|
1610 |
|
1611 |
+
if (2 !== \count($operators)) {
|
1612 |
+
throw new \InvalidArgumentException(sprintf('"%s::getOperators()" must return an array of 2 elements, got %d.', \get_class($extension), \count($operators)));
|
1613 |
}
|
1614 |
|
1615 |
$this->unaryOperators = array_merge($this->unaryOperators, $operators[0]);
|
1630 |
$hashParts = array_merge(
|
1631 |
array_keys($this->extensions),
|
1632 |
[
|
1633 |
+
(int) \function_exists('twig_template_get_attributes'),
|
1634 |
PHP_MAJOR_VERSION,
|
1635 |
PHP_MINOR_VERSION,
|
1636 |
self::VERSION,
|
vendor/twig/twig/lib/Twig/Error.php
CHANGED
@@ -9,6 +9,9 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Twig base exception.
|
14 |
*
|
@@ -31,7 +34,7 @@
|
|
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
|
@@ -53,16 +56,16 @@ class Twig_Error extends Exception
|
|
53 |
*
|
54 |
* By default, automatic guessing is enabled.
|
55 |
*
|
56 |
-
* @param string
|
57 |
-
* @param int
|
58 |
-
* @param
|
59 |
-
* @param 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
|
66 |
// for compat with the Twig C ext., passing the template name as string is accepted
|
67 |
$name = $source;
|
68 |
} else {
|
@@ -180,17 +183,17 @@ class Twig_Error extends Exception
|
|
180 |
/**
|
181 |
* Gets the source context of the Twig template where the error occurred.
|
182 |
*
|
183 |
-
* @return
|
184 |
*/
|
185 |
public function getSourceContext()
|
186 |
{
|
187 |
-
return $this->filename ? new
|
188 |
}
|
189 |
|
190 |
/**
|
191 |
* Sets the source context of the Twig template where the error occurred.
|
192 |
*/
|
193 |
-
public function setSourceContext(
|
194 |
{
|
195 |
if (null === $source) {
|
196 |
$this->sourceCode = $this->filename = $this->sourcePath = null;
|
@@ -242,7 +245,7 @@ class Twig_Error extends Exception
|
|
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);
|
@@ -273,12 +276,12 @@ class Twig_Error extends Exception
|
|
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
|
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 |
}
|
@@ -299,7 +302,7 @@ class Twig_Error extends Exception
|
|
299 |
return;
|
300 |
}
|
301 |
|
302 |
-
$r = new ReflectionObject($template);
|
303 |
$file = $r->getFileName();
|
304 |
|
305 |
$exceptions = [$e = $this];
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Source;
|
13 |
+
use Twig\Template;
|
14 |
+
|
15 |
/**
|
16 |
* Twig base exception.
|
17 |
*
|
34 |
*
|
35 |
* @author Fabien Potencier <fabien@symfony.com>
|
36 |
*/
|
37 |
+
class Twig_Error extends \Exception
|
38 |
{
|
39 |
protected $lineno;
|
40 |
// to be renamed to name in 2.0
|
56 |
*
|
57 |
* By default, automatic guessing is enabled.
|
58 |
*
|
59 |
+
* @param string $message The error message
|
60 |
+
* @param int $lineno The template line where the error occurred
|
61 |
+
* @param Source|string|null $source The source context where the error occurred
|
62 |
+
* @param \Exception $previous The previous exception
|
63 |
*/
|
64 |
+
public function __construct($message, $lineno = -1, $source = null, \Exception $previous = null)
|
65 |
{
|
66 |
if (null === $source) {
|
67 |
$name = null;
|
68 |
+
} elseif (!$source instanceof Source) {
|
69 |
// for compat with the Twig C ext., passing the template name as string is accepted
|
70 |
$name = $source;
|
71 |
} else {
|
183 |
/**
|
184 |
* Gets the source context of the Twig template where the error occurred.
|
185 |
*
|
186 |
+
* @return Source|null
|
187 |
*/
|
188 |
public function getSourceContext()
|
189 |
{
|
190 |
+
return $this->filename ? new Source($this->sourceCode, $this->filename, $this->sourcePath) : null;
|
191 |
}
|
192 |
|
193 |
/**
|
194 |
* Sets the source context of the Twig template where the error occurred.
|
195 |
*/
|
196 |
+
public function setSourceContext(Source $source = null)
|
197 |
{
|
198 |
if (null === $source) {
|
199 |
$this->sourceCode = $this->filename = $this->sourcePath = null;
|
245 |
}
|
246 |
|
247 |
if ($this->filename) {
|
248 |
+
if (\is_string($this->filename) || (\is_object($this->filename) && method_exists($this->filename, '__toString'))) {
|
249 |
$name = sprintf('"%s"', $this->filename);
|
250 |
} else {
|
251 |
$name = json_encode($this->filename);
|
276 |
|
277 |
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT);
|
278 |
foreach ($backtrace as $trace) {
|
279 |
+
if (isset($trace['object']) && $trace['object'] instanceof Template && 'Twig_Template' !== \get_class($trace['object'])) {
|
280 |
+
$currentClass = \get_class($trace['object']);
|
281 |
$isEmbedContainer = 0 === strpos($templateClass, $currentClass);
|
282 |
if (null === $this->filename || ($this->filename == $trace['object']->getTemplateName() && !$isEmbedContainer)) {
|
283 |
$template = $trace['object'];
|
284 |
+
$templateClass = \get_class($trace['object']);
|
285 |
}
|
286 |
}
|
287 |
}
|
302 |
return;
|
303 |
}
|
304 |
|
305 |
+
$r = new \ReflectionObject($template);
|
306 |
$file = $r->getFileName();
|
307 |
|
308 |
$exceptions = [$e = $this];
|
vendor/twig/twig/lib/Twig/Error/Loader.php
CHANGED
@@ -9,6 +9,8 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
12 |
/**
|
13 |
* Exception thrown when an error occurs during template loading.
|
14 |
*
|
@@ -16,17 +18,17 @@
|
|
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 |
-
*
|
20 |
*
|
21 |
-
* This strategy makes
|
22 |
*
|
23 |
* @author Fabien Potencier <fabien@symfony.com>
|
24 |
*/
|
25 |
-
class Twig_Error_Loader extends
|
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);
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Error\Error;
|
13 |
+
|
14 |
/**
|
15 |
* Exception thrown when an error occurs during template loading.
|
16 |
*
|
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 Twig_Error_Loader extends Error
|
28 |
{
|
29 |
+
public function __construct($message, $lineno = -1, $source = null, \Exception $previous = null)
|
30 |
{
|
31 |
+
\Exception::__construct('', 0, $previous);
|
32 |
|
33 |
$this->appendMessage($message);
|
34 |
$this->setTemplateLine(false);
|
vendor/twig/twig/lib/Twig/Error/Runtime.php
CHANGED
@@ -10,12 +10,14 @@
|
|
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
|
19 |
{
|
20 |
}
|
21 |
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Error\Error;
|
14 |
+
|
15 |
/**
|
16 |
* Exception thrown when an error occurs at runtime.
|
17 |
*
|
18 |
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
*/
|
20 |
+
class Twig_Error_Runtime extends Error
|
21 |
{
|
22 |
}
|
23 |
|
vendor/twig/twig/lib/Twig/Error/Syntax.php
CHANGED
@@ -10,12 +10,14 @@
|
|
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
|
19 |
{
|
20 |
/**
|
21 |
* Tweaks the error message to include suggestions.
|
@@ -42,7 +44,7 @@ class Twig_Error_Syntax extends Twig_Error
|
|
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 |
}
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Error\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 Twig_Error_Syntax extends Error
|
21 |
{
|
22 |
/**
|
23 |
* Tweaks the error message to include suggestions.
|
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 |
}
|
vendor/twig/twig/lib/Twig/ExpressionParser.php
CHANGED
@@ -10,6 +10,30 @@
|
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
/**
|
14 |
* Parses expressions.
|
15 |
*
|
@@ -33,11 +57,11 @@ class Twig_ExpressionParser
|
|
33 |
|
34 |
private $env;
|
35 |
|
36 |
-
public function __construct(
|
37 |
{
|
38 |
$this->parser = $parser;
|
39 |
|
40 |
-
if ($env instanceof
|
41 |
$this->env = $env;
|
42 |
$this->unaryOperators = $env->getUnaryOperators();
|
43 |
$this->binaryOperators = $env->getBinaryOperators();
|
@@ -63,7 +87,7 @@ class Twig_ExpressionParser
|
|
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'];
|
@@ -91,10 +115,10 @@ class Twig_ExpressionParser
|
|
91 |
$class = $operator['class'];
|
92 |
|
93 |
return $this->parsePostfixExpression(new $class($expr, $token->getLine()));
|
94 |
-
} elseif ($token->test(
|
95 |
$this->parser->getStream()->next();
|
96 |
$expr = $this->parseExpression();
|
97 |
-
$this->parser->getStream()->expect(
|
98 |
|
99 |
return $this->parsePostfixExpression($expr);
|
100 |
}
|
@@ -104,92 +128,92 @@ class Twig_ExpressionParser
|
|
104 |
|
105 |
protected function parseConditionalExpression($expr)
|
106 |
{
|
107 |
-
while ($this->parser->getStream()->nextIf(
|
108 |
-
if (!$this->parser->getStream()->nextIf(
|
109 |
$expr2 = $this->parseExpression();
|
110 |
-
if ($this->parser->getStream()->nextIf(
|
111 |
$expr3 = $this->parseExpression();
|
112 |
} else {
|
113 |
-
$expr3 = new
|
114 |
}
|
115 |
} else {
|
116 |
$expr2 = $expr;
|
117 |
$expr3 = $this->parseExpression();
|
118 |
}
|
119 |
|
120 |
-
$expr = new
|
121 |
}
|
122 |
|
123 |
return $expr;
|
124 |
}
|
125 |
|
126 |
-
protected function isUnary(
|
127 |
{
|
128 |
-
return $token->test(
|
129 |
}
|
130 |
|
131 |
-
protected function isBinary(
|
132 |
{
|
133 |
-
return $token->test(
|
134 |
}
|
135 |
|
136 |
public function parsePrimaryExpression()
|
137 |
{
|
138 |
$token = $this->parser->getCurrentToken();
|
139 |
switch ($token->getType()) {
|
140 |
-
case
|
141 |
$this->parser->getStream()->next();
|
142 |
switch ($token->getValue()) {
|
143 |
case 'true':
|
144 |
case 'TRUE':
|
145 |
-
$node = new
|
146 |
break;
|
147 |
|
148 |
case 'false':
|
149 |
case 'FALSE':
|
150 |
-
$node = new
|
151 |
break;
|
152 |
|
153 |
case 'none':
|
154 |
case 'NONE':
|
155 |
case 'null':
|
156 |
case 'NULL':
|
157 |
-
$node = new
|
158 |
break;
|
159 |
|
160 |
default:
|
161 |
if ('(' === $this->parser->getCurrentToken()->getValue()) {
|
162 |
$node = $this->getFunctionNode($token->getValue(), $token->getLine());
|
163 |
} else {
|
164 |
-
$node = new
|
165 |
}
|
166 |
}
|
167 |
break;
|
168 |
|
169 |
-
case
|
170 |
$this->parser->getStream()->next();
|
171 |
-
$node = new
|
172 |
break;
|
173 |
|
174 |
-
case
|
175 |
-
case
|
176 |
$node = $this->parseStringExpression();
|
177 |
break;
|
178 |
|
179 |
-
case
|
180 |
-
if (preg_match(
|
181 |
// in this context, string operators are variable names
|
182 |
$this->parser->getStream()->next();
|
183 |
-
$node = new
|
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
|
193 |
}
|
194 |
|
195 |
$this->parser->getStream()->next();
|
@@ -201,14 +225,14 @@ class Twig_ExpressionParser
|
|
201 |
|
202 |
// no break
|
203 |
default:
|
204 |
-
if ($token->test(
|
205 |
$node = $this->parseArrayExpression();
|
206 |
-
} elseif ($token->test(
|
207 |
$node = $this->parseHashExpression();
|
208 |
-
} elseif ($token->test(
|
209 |
-
throw new
|
210 |
} else {
|
211 |
-
throw new
|
212 |
}
|
213 |
}
|
214 |
|
@@ -223,12 +247,12 @@ class Twig_ExpressionParser
|
|
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(
|
227 |
-
$nodes[] = new
|
228 |
$nextCanBeString = false;
|
229 |
-
} elseif ($stream->nextIf(
|
230 |
$nodes[] = $this->parseExpression();
|
231 |
-
$stream->expect(
|
232 |
$nextCanBeString = true;
|
233 |
} else {
|
234 |
break;
|
@@ -237,7 +261,7 @@ class Twig_ExpressionParser
|
|
237 |
|
238 |
$expr = array_shift($nodes);
|
239 |
foreach ($nodes as $node) {
|
240 |
-
$expr = new
|
241 |
}
|
242 |
|
243 |
return $expr;
|
@@ -246,16 +270,16 @@ class Twig_ExpressionParser
|
|
246 |
public function parseArrayExpression()
|
247 |
{
|
248 |
$stream = $this->parser->getStream();
|
249 |
-
$stream->expect(
|
250 |
|
251 |
-
$node = new
|
252 |
$first = true;
|
253 |
-
while (!$stream->test(
|
254 |
if (!$first) {
|
255 |
-
$stream->expect(
|
256 |
|
257 |
// trailing ,?
|
258 |
-
if ($stream->test(
|
259 |
break;
|
260 |
}
|
261 |
}
|
@@ -263,7 +287,7 @@ class Twig_ExpressionParser
|
|
263 |
|
264 |
$node->addElement($this->parseExpression());
|
265 |
}
|
266 |
-
$stream->expect(
|
267 |
|
268 |
return $node;
|
269 |
}
|
@@ -271,16 +295,16 @@ class Twig_ExpressionParser
|
|
271 |
public function parseHashExpression()
|
272 |
{
|
273 |
$stream = $this->parser->getStream();
|
274 |
-
$stream->expect(
|
275 |
|
276 |
-
$node = new
|
277 |
$first = true;
|
278 |
-
while (!$stream->test(
|
279 |
if (!$first) {
|
280 |
-
$stream->expect(
|
281 |
|
282 |
// trailing ,?
|
283 |
-
if ($stream->test(
|
284 |
break;
|
285 |
}
|
286 |
}
|
@@ -292,22 +316,22 @@ class Twig_ExpressionParser
|
|
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(
|
296 |
-
$key = new
|
297 |
-
} elseif ($stream->test(
|
298 |
$key = $this->parseExpression();
|
299 |
} else {
|
300 |
$current = $stream->getCurrent();
|
301 |
|
302 |
-
throw new
|
303 |
}
|
304 |
|
305 |
-
$stream->expect(
|
306 |
$value = $this->parseExpression();
|
307 |
|
308 |
$node->addElement($value, $key);
|
309 |
}
|
310 |
-
$stream->expect(
|
311 |
|
312 |
return $node;
|
313 |
}
|
@@ -316,7 +340,7 @@ class Twig_ExpressionParser
|
|
316 |
{
|
317 |
while (true) {
|
318 |
$token = $this->parser->getCurrentToken();
|
319 |
-
if (
|
320 |
if ('.' == $token->getValue() || '[' == $token->getValue()) {
|
321 |
$node = $this->parseSubscriptExpression($node);
|
322 |
} elseif ('|' == $token->getValue()) {
|
@@ -337,37 +361,37 @@ class Twig_ExpressionParser
|
|
337 |
switch ($name) {
|
338 |
case 'parent':
|
339 |
$this->parseArguments();
|
340 |
-
if (
|
341 |
-
throw new
|
342 |
}
|
343 |
|
344 |
if (!$this->parser->getParent() && !$this->parser->hasTraits()) {
|
345 |
-
throw new
|
346 |
}
|
347 |
|
348 |
-
return new
|
349 |
case 'block':
|
350 |
$args = $this->parseArguments();
|
351 |
-
if (count($args) < 1) {
|
352 |
-
throw new
|
353 |
}
|
354 |
|
355 |
-
return new
|
356 |
case 'attribute':
|
357 |
$args = $this->parseArguments();
|
358 |
-
if (count($args) < 2) {
|
359 |
-
throw new
|
360 |
}
|
361 |
|
362 |
-
return new
|
363 |
default:
|
364 |
if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) {
|
365 |
-
$arguments = new
|
366 |
foreach ($this->parseArguments() as $n) {
|
367 |
$arguments->addElement($n);
|
368 |
}
|
369 |
|
370 |
-
$node = new
|
371 |
$node->setAttribute('safe', true);
|
372 |
|
373 |
return $node;
|
@@ -385,81 +409,81 @@ class Twig_ExpressionParser
|
|
385 |
$stream = $this->parser->getStream();
|
386 |
$token = $stream->next();
|
387 |
$lineno = $token->getLine();
|
388 |
-
$arguments = new
|
389 |
-
$type =
|
390 |
if ('.' == $token->getValue()) {
|
391 |
$token = $stream->next();
|
392 |
if (
|
393 |
-
|
394 |
||
|
395 |
-
|
396 |
||
|
397 |
-
(
|
398 |
) {
|
399 |
-
$arg = new
|
400 |
|
401 |
-
if ($stream->test(
|
402 |
-
$type =
|
403 |
foreach ($this->parseArguments() as $n) {
|
404 |
$arguments->addElement($n);
|
405 |
}
|
406 |
}
|
407 |
} else {
|
408 |
-
throw new
|
409 |
}
|
410 |
|
411 |
-
if ($node instanceof
|
412 |
-
if (!$arg instanceof
|
413 |
-
throw new
|
414 |
}
|
415 |
|
416 |
$name = $arg->getAttribute('value');
|
417 |
|
418 |
if ($this->parser->isReservedMacroName($name)) {
|
419 |
-
throw new
|
420 |
}
|
421 |
|
422 |
-
$node = new
|
423 |
$node->setAttribute('safe', true);
|
424 |
|
425 |
return $node;
|
426 |
}
|
427 |
} else {
|
428 |
-
$type =
|
429 |
|
430 |
// slice?
|
431 |
$slice = false;
|
432 |
-
if ($stream->test(
|
433 |
$slice = true;
|
434 |
-
$arg = new
|
435 |
} else {
|
436 |
$arg = $this->parseExpression();
|
437 |
}
|
438 |
|
439 |
-
if ($stream->nextIf(
|
440 |
$slice = true;
|
441 |
}
|
442 |
|
443 |
if ($slice) {
|
444 |
-
if ($stream->test(
|
445 |
-
$length = new
|
446 |
} else {
|
447 |
$length = $this->parseExpression();
|
448 |
}
|
449 |
|
450 |
$class = $this->getFilterNodeClass('slice', $token->getLine());
|
451 |
-
$arguments = new
|
452 |
-
$filter = new $class($node, new
|
453 |
|
454 |
-
$stream->expect(
|
455 |
|
456 |
return $filter;
|
457 |
}
|
458 |
|
459 |
-
$stream->expect(
|
460 |
}
|
461 |
|
462 |
-
return new
|
463 |
}
|
464 |
|
465 |
public function parseFilterExpression($node)
|
@@ -472,11 +496,11 @@ class Twig_ExpressionParser
|
|
472 |
public function parseFilterExpressionRaw($node, $tag = null)
|
473 |
{
|
474 |
while (true) {
|
475 |
-
$token = $this->parser->getStream()->expect(
|
476 |
|
477 |
-
$name = new
|
478 |
-
if (!$this->parser->getStream()->test(
|
479 |
-
$arguments = new
|
480 |
} else {
|
481 |
$arguments = $this->parseArguments(true);
|
482 |
}
|
@@ -485,7 +509,7 @@ class Twig_ExpressionParser
|
|
485 |
|
486 |
$node = new $class($node, $name, $arguments, $token->getLine(), $tag);
|
487 |
|
488 |
-
if (!$this->parser->getStream()->test(
|
489 |
break;
|
490 |
}
|
491 |
|
@@ -501,32 +525,32 @@ class Twig_ExpressionParser
|
|
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
|
505 |
*
|
506 |
-
* @throws
|
507 |
*/
|
508 |
public function parseArguments($namedArguments = false, $definition = false)
|
509 |
{
|
510 |
$args = [];
|
511 |
$stream = $this->parser->getStream();
|
512 |
|
513 |
-
$stream->expect(
|
514 |
-
while (!$stream->test(
|
515 |
if (!empty($args)) {
|
516 |
-
$stream->expect(
|
517 |
}
|
518 |
|
519 |
if ($definition) {
|
520 |
-
$token = $stream->expect(
|
521 |
-
$value = new
|
522 |
} else {
|
523 |
$value = $this->parseExpression();
|
524 |
}
|
525 |
|
526 |
$name = null;
|
527 |
-
if ($namedArguments && $token = $stream->nextIf(
|
528 |
-
if (!$value instanceof
|
529 |
-
throw new
|
530 |
}
|
531 |
$name = $value->getAttribute('name');
|
532 |
|
@@ -534,7 +558,7 @@ class Twig_ExpressionParser
|
|
534 |
$value = $this->parsePrimaryExpression();
|
535 |
|
536 |
if (!$this->checkConstantExpression($value)) {
|
537 |
-
throw new
|
538 |
}
|
539 |
} else {
|
540 |
$value = $this->parseExpression();
|
@@ -544,7 +568,7 @@ class Twig_ExpressionParser
|
|
544 |
if ($definition) {
|
545 |
if (null === $name) {
|
546 |
$name = $value->getAttribute('name');
|
547 |
-
$value = new
|
548 |
}
|
549 |
$args[$name] = $value;
|
550 |
} else {
|
@@ -555,9 +579,9 @@ class Twig_ExpressionParser
|
|
555 |
}
|
556 |
}
|
557 |
}
|
558 |
-
$stream->expect(
|
559 |
|
560 |
-
return new
|
561 |
}
|
562 |
|
563 |
public function parseAssignmentExpression()
|
@@ -565,19 +589,19 @@ class Twig_ExpressionParser
|
|
565 |
$stream = $this->parser->getStream();
|
566 |
$targets = [];
|
567 |
while (true) {
|
568 |
-
$token = $stream->expect(
|
569 |
$value = $token->getValue();
|
570 |
-
if (in_array(strtolower($value), ['true', 'false', 'none', 'null'])) {
|
571 |
-
throw new
|
572 |
}
|
573 |
-
$targets[] = new
|
574 |
|
575 |
-
if (!$stream->nextIf(
|
576 |
break;
|
577 |
}
|
578 |
}
|
579 |
|
580 |
-
return new
|
581 |
}
|
582 |
|
583 |
public function parseMultitargetExpression()
|
@@ -585,17 +609,17 @@ class Twig_ExpressionParser
|
|
585 |
$targets = [];
|
586 |
while (true) {
|
587 |
$targets[] = $this->parseExpression();
|
588 |
-
if (!$this->parser->getStream()->nextIf(
|
589 |
break;
|
590 |
}
|
591 |
}
|
592 |
|
593 |
-
return new
|
594 |
}
|
595 |
|
596 |
private function parseNotTestExpression(Twig_NodeInterface $node)
|
597 |
{
|
598 |
-
return new
|
599 |
}
|
600 |
|
601 |
private function parseTestExpression(Twig_NodeInterface $node)
|
@@ -605,7 +629,7 @@ class Twig_ExpressionParser
|
|
605 |
|
606 |
$class = $this->getTestNodeClass($test);
|
607 |
$arguments = null;
|
608 |
-
if ($stream->test(
|
609 |
$arguments = $this->parser->getExpressionParser()->parseArguments(true);
|
610 |
}
|
611 |
|
@@ -615,13 +639,13 @@ class Twig_ExpressionParser
|
|
615 |
private function getTest($line)
|
616 |
{
|
617 |
$stream = $this->parser->getStream();
|
618 |
-
$name = $stream->expect(
|
619 |
|
620 |
if ($test = $this->env->getTest($name)) {
|
621 |
return [$name, $test];
|
622 |
}
|
623 |
|
624 |
-
if ($stream->test(
|
625 |
// try 2-words tests
|
626 |
$name = $name.' '.$this->parser->getCurrentToken()->getValue();
|
627 |
|
@@ -632,7 +656,7 @@ class Twig_ExpressionParser
|
|
632 |
}
|
633 |
}
|
634 |
|
635 |
-
$e = new
|
636 |
$e->addSuggestions($name, array_keys($this->env->getTests()));
|
637 |
|
638 |
throw $e;
|
@@ -640,10 +664,10 @@ class Twig_ExpressionParser
|
|
640 |
|
641 |
private function getTestNodeClass($test)
|
642 |
{
|
643 |
-
if ($test instanceof
|
644 |
$stream = $this->parser->getStream();
|
645 |
$message = sprintf('Twig Test "%s" is deprecated', $test->getName());
|
646 |
-
if (
|
647 |
$message .= sprintf(' since version %s', $test->getDeprecatedVersion());
|
648 |
}
|
649 |
if ($test->getAlternative()) {
|
@@ -655,7 +679,7 @@ class Twig_ExpressionParser
|
|
655 |
@trigger_error($message, E_USER_DEPRECATED);
|
656 |
}
|
657 |
|
658 |
-
if ($test instanceof
|
659 |
return $test->getNodeClass();
|
660 |
}
|
661 |
|
@@ -665,15 +689,15 @@ class Twig_ExpressionParser
|
|
665 |
protected function getFunctionNodeClass($name, $line)
|
666 |
{
|
667 |
if (false === $function = $this->env->getFunction($name)) {
|
668 |
-
$e = new
|
669 |
$e->addSuggestions($name, array_keys($this->env->getFunctions()));
|
670 |
|
671 |
throw $e;
|
672 |
}
|
673 |
|
674 |
-
if ($function instanceof
|
675 |
$message = sprintf('Twig Function "%s" is deprecated', $function->getName());
|
676 |
-
if (
|
677 |
$message .= sprintf(' since version %s', $function->getDeprecatedVersion());
|
678 |
}
|
679 |
if ($function->getAlternative()) {
|
@@ -685,7 +709,7 @@ class Twig_ExpressionParser
|
|
685 |
@trigger_error($message, E_USER_DEPRECATED);
|
686 |
}
|
687 |
|
688 |
-
if ($function instanceof
|
689 |
return $function->getNodeClass();
|
690 |
}
|
691 |
|
@@ -695,15 +719,15 @@ class Twig_ExpressionParser
|
|
695 |
protected function getFilterNodeClass($name, $line)
|
696 |
{
|
697 |
if (false === $filter = $this->env->getFilter($name)) {
|
698 |
-
$e = new
|
699 |
$e->addSuggestions($name, array_keys($this->env->getFilters()));
|
700 |
|
701 |
throw $e;
|
702 |
}
|
703 |
|
704 |
-
if ($filter instanceof
|
705 |
$message = sprintf('Twig Filter "%s" is deprecated', $filter->getName());
|
706 |
-
if (
|
707 |
$message .= sprintf(' since version %s', $filter->getDeprecatedVersion());
|
708 |
}
|
709 |
if ($filter->getAlternative()) {
|
@@ -715,7 +739,7 @@ class Twig_ExpressionParser
|
|
715 |
@trigger_error($message, E_USER_DEPRECATED);
|
716 |
}
|
717 |
|
718 |
-
if ($filter instanceof
|
719 |
return $filter->getNodeClass();
|
720 |
}
|
721 |
|
@@ -725,8 +749,8 @@ class Twig_ExpressionParser
|
|
725 |
// checks that the node only contains "constant" elements
|
726 |
protected function checkConstantExpression(Twig_NodeInterface $node)
|
727 |
{
|
728 |
-
if (!($node instanceof
|
729 |
-
|| $node instanceof
|
730 |
)) {
|
731 |
return false;
|
732 |
}
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Environment;
|
14 |
+
use Twig\Error\SyntaxError;
|
15 |
+
use Twig\Lexer;
|
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 |
+
use Twig\Parser;
|
31 |
+
use Twig\Template;
|
32 |
+
use Twig\Token;
|
33 |
+
use Twig\TwigFilter;
|
34 |
+
use Twig\TwigFunction;
|
35 |
+
use Twig\TwigTest;
|
36 |
+
|
37 |
/**
|
38 |
* Parses expressions.
|
39 |
*
|
57 |
|
58 |
private $env;
|
59 |
|
60 |
+
public function __construct(Parser $parser, $env = null)
|
61 |
{
|
62 |
$this->parser = $parser;
|
63 |
|
64 |
+
if ($env instanceof Environment) {
|
65 |
$this->env = $env;
|
66 |
$this->unaryOperators = $env->getUnaryOperators();
|
67 |
$this->binaryOperators = $env->getBinaryOperators();
|
87 |
} elseif ('is' === $token->getValue()) {
|
88 |
$expr = $this->parseTestExpression($expr);
|
89 |
} elseif (isset($op['callable'])) {
|
90 |
+
$expr = \call_user_func($op['callable'], $this->parser, $expr);
|
91 |
} else {
|
92 |
$expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']);
|
93 |
$class = $op['class'];
|
115 |
$class = $operator['class'];
|
116 |
|
117 |
return $this->parsePostfixExpression(new $class($expr, $token->getLine()));
|
118 |
+
} elseif ($token->test(Token::PUNCTUATION_TYPE, '(')) {
|
119 |
$this->parser->getStream()->next();
|
120 |
$expr = $this->parseExpression();
|
121 |
+
$this->parser->getStream()->expect(Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed');
|
122 |
|
123 |
return $this->parsePostfixExpression($expr);
|
124 |
}
|
128 |
|
129 |
protected function parseConditionalExpression($expr)
|
130 |
{
|
131 |
+
while ($this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, '?')) {
|
132 |
+
if (!$this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, ':')) {
|
133 |
$expr2 = $this->parseExpression();
|
134 |
+
if ($this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, ':')) {
|
135 |
$expr3 = $this->parseExpression();
|
136 |
} else {
|
137 |
+
$expr3 = new ConstantExpression('', $this->parser->getCurrentToken()->getLine());
|
138 |
}
|
139 |
} else {
|
140 |
$expr2 = $expr;
|
141 |
$expr3 = $this->parseExpression();
|
142 |
}
|
143 |
|
144 |
+
$expr = new ConditionalExpression($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine());
|
145 |
}
|
146 |
|
147 |
return $expr;
|
148 |
}
|
149 |
|
150 |
+
protected function isUnary(Token $token)
|
151 |
{
|
152 |
+
return $token->test(Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]);
|
153 |
}
|
154 |
|
155 |
+
protected function isBinary(Token $token)
|
156 |
{
|
157 |
+
return $token->test(Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]);
|
158 |
}
|
159 |
|
160 |
public function parsePrimaryExpression()
|
161 |
{
|
162 |
$token = $this->parser->getCurrentToken();
|
163 |
switch ($token->getType()) {
|
164 |
+
case Token::NAME_TYPE:
|
165 |
$this->parser->getStream()->next();
|
166 |
switch ($token->getValue()) {
|
167 |
case 'true':
|
168 |
case 'TRUE':
|
169 |
+
$node = new ConstantExpression(true, $token->getLine());
|
170 |
break;
|
171 |
|
172 |
case 'false':
|
173 |
case 'FALSE':
|
174 |
+
$node = new ConstantExpression(false, $token->getLine());
|
175 |
break;
|
176 |
|
177 |
case 'none':
|
178 |
case 'NONE':
|
179 |
case 'null':
|
180 |
case 'NULL':
|
181 |
+
$node = new ConstantExpression(null, $token->getLine());
|
182 |
break;
|
183 |
|
184 |
default:
|
185 |
if ('(' === $this->parser->getCurrentToken()->getValue()) {
|
186 |
$node = $this->getFunctionNode($token->getValue(), $token->getLine());
|
187 |
} else {
|
188 |
+
$node = new NameExpression($token->getValue(), $token->getLine());
|
189 |
}
|
190 |
}
|
191 |
break;
|
192 |
|
193 |
+
case Token::NUMBER_TYPE:
|
194 |
$this->parser->getStream()->next();
|
195 |
+
$node = new ConstantExpression($token->getValue(), $token->getLine());
|
196 |
break;
|
197 |
|
198 |
+
case Token::STRING_TYPE:
|
199 |
+
case Token::INTERPOLATION_START_TYPE:
|
200 |
$node = $this->parseStringExpression();
|
201 |
break;
|
202 |
|
203 |
+
case Token::OPERATOR_TYPE:
|
204 |
+
if (preg_match(Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) {
|
205 |
// in this context, string operators are variable names
|
206 |
$this->parser->getStream()->next();
|
207 |
+
$node = new NameExpression($token->getValue(), $token->getLine());
|
208 |
break;
|
209 |
} elseif (isset($this->unaryOperators[$token->getValue()])) {
|
210 |
$class = $this->unaryOperators[$token->getValue()]['class'];
|
211 |
|
212 |
+
$ref = new \ReflectionClass($class);
|
213 |
$negClass = 'Twig_Node_Expression_Unary_Neg';
|
214 |
$posClass = 'Twig_Node_Expression_Unary_Pos';
|
215 |
+
if (!(\in_array($ref->getName(), [$negClass, $posClass]) || $ref->isSubclassOf($negClass) || $ref->isSubclassOf($posClass))) {
|
216 |
+
throw new SyntaxError(sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext());
|
217 |
}
|
218 |
|
219 |
$this->parser->getStream()->next();
|
225 |
|
226 |
// no break
|
227 |
default:
|
228 |
+
if ($token->test(Token::PUNCTUATION_TYPE, '[')) {
|
229 |
$node = $this->parseArrayExpression();
|
230 |
+
} elseif ($token->test(Token::PUNCTUATION_TYPE, '{')) {
|
231 |
$node = $this->parseHashExpression();
|
232 |
+
} elseif ($token->test(Token::OPERATOR_TYPE, '=') && ('==' === $this->parser->getStream()->look(-1)->getValue() || '!=' === $this->parser->getStream()->look(-1)->getValue())) {
|
233 |
+
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());
|
234 |
} else {
|
235 |
+
throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s".', Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext());
|
236 |
}
|
237 |
}
|
238 |
|
247 |
// a string cannot be followed by another string in a single expression
|
248 |
$nextCanBeString = true;
|
249 |
while (true) {
|
250 |
+
if ($nextCanBeString && $token = $stream->nextIf(Token::STRING_TYPE)) {
|
251 |
+
$nodes[] = new ConstantExpression($token->getValue(), $token->getLine());
|
252 |
$nextCanBeString = false;
|
253 |
+
} elseif ($stream->nextIf(Token::INTERPOLATION_START_TYPE)) {
|
254 |
$nodes[] = $this->parseExpression();
|
255 |
+
$stream->expect(Token::INTERPOLATION_END_TYPE);
|
256 |
$nextCanBeString = true;
|
257 |
} else {
|
258 |
break;
|
261 |
|
262 |
$expr = array_shift($nodes);
|
263 |
foreach ($nodes as $node) {
|
264 |
+
$expr = new ConcatBinary($expr, $node, $node->getTemplateLine());
|
265 |
}
|
266 |
|
267 |
return $expr;
|
270 |
public function parseArrayExpression()
|
271 |
{
|
272 |
$stream = $this->parser->getStream();
|
273 |
+
$stream->expect(Token::PUNCTUATION_TYPE, '[', 'An array element was expected');
|
274 |
|
275 |
+
$node = new ArrayExpression([], $stream->getCurrent()->getLine());
|
276 |
$first = true;
|
277 |
+
while (!$stream->test(Token::PUNCTUATION_TYPE, ']')) {
|
278 |
if (!$first) {
|
279 |
+
$stream->expect(Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma');
|
280 |
|
281 |
// trailing ,?
|
282 |
+
if ($stream->test(Token::PUNCTUATION_TYPE, ']')) {
|
283 |
break;
|
284 |
}
|
285 |
}
|
287 |
|
288 |
$node->addElement($this->parseExpression());
|
289 |
}
|
290 |
+
$stream->expect(Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed');
|
291 |
|
292 |
return $node;
|
293 |
}
|
295 |
public function parseHashExpression()
|
296 |
{
|
297 |
$stream = $this->parser->getStream();
|
298 |
+
$stream->expect(Token::PUNCTUATION_TYPE, '{', 'A hash element was expected');
|
299 |
|
300 |
+
$node = new ArrayExpression([], $stream->getCurrent()->getLine());
|
301 |
$first = true;
|
302 |
+
while (!$stream->test(Token::PUNCTUATION_TYPE, '}')) {
|
303 |
if (!$first) {
|
304 |
+
$stream->expect(Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma');
|
305 |
|
306 |
// trailing ,?
|
307 |
+
if ($stream->test(Token::PUNCTUATION_TYPE, '}')) {
|
308 |
break;
|
309 |
}
|
310 |
}
|
316 |
// * a string -- 'a'
|
317 |
// * a name, which is equivalent to a string -- a
|
318 |
// * an expression, which must be enclosed in parentheses -- (1 + 2)
|
319 |
+
if (($token = $stream->nextIf(Token::STRING_TYPE)) || ($token = $stream->nextIf(Token::NAME_TYPE)) || $token = $stream->nextIf(Token::NUMBER_TYPE)) {
|
320 |
+
$key = new ConstantExpression($token->getValue(), $token->getLine());
|
321 |
+
} elseif ($stream->test(Token::PUNCTUATION_TYPE, '(')) {
|
322 |
$key = $this->parseExpression();
|
323 |
} else {
|
324 |
$current = $stream->getCurrent();
|
325 |
|
326 |
+
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());
|
327 |
}
|
328 |
|
329 |
+
$stream->expect(Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)');
|
330 |
$value = $this->parseExpression();
|
331 |
|
332 |
$node->addElement($value, $key);
|
333 |
}
|
334 |
+
$stream->expect(Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed');
|
335 |
|
336 |
return $node;
|
337 |
}
|
340 |
{
|
341 |
while (true) {
|
342 |
$token = $this->parser->getCurrentToken();
|
343 |
+
if (Token::PUNCTUATION_TYPE == $token->getType()) {
|
344 |
if ('.' == $token->getValue() || '[' == $token->getValue()) {
|
345 |
$node = $this->parseSubscriptExpression($node);
|
346 |
} elseif ('|' == $token->getValue()) {
|
361 |
switch ($name) {
|
362 |
case 'parent':
|
363 |
$this->parseArguments();
|
364 |
+
if (!\count($this->parser->getBlockStack())) {
|
365 |
+
throw new SyntaxError('Calling "parent" outside a block is forbidden.', $line, $this->parser->getStream()->getSourceContext());
|
366 |
}
|
367 |
|
368 |
if (!$this->parser->getParent() && !$this->parser->hasTraits()) {
|
369 |
+
throw new SyntaxError('Calling "parent" on a template that does not extend nor "use" another template is forbidden.', $line, $this->parser->getStream()->getSourceContext());
|
370 |
}
|
371 |
|
372 |
+
return new ParentExpression($this->parser->peekBlockStack(), $line);
|
373 |
case 'block':
|
374 |
$args = $this->parseArguments();
|
375 |
+
if (\count($args) < 1) {
|
376 |
+
throw new SyntaxError('The "block" function takes one argument (the block name).', $line, $this->parser->getStream()->getSourceContext());
|
377 |
}
|
378 |
|
379 |
+
return new BlockReferenceExpression($args->getNode(0), \count($args) > 1 ? $args->getNode(1) : null, $line);
|
380 |
case 'attribute':
|
381 |
$args = $this->parseArguments();
|
382 |
+
if (\count($args) < 2) {
|
383 |
+
throw new SyntaxError('The "attribute" function takes at least two arguments (the variable and the attributes).', $line, $this->parser->getStream()->getSourceContext());
|
384 |
}
|
385 |
|
386 |
+
return new GetAttrExpression($args->getNode(0), $args->getNode(1), \count($args) > 2 ? $args->getNode(2) : null, Template::ANY_CALL, $line);
|
387 |
default:
|
388 |
if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) {
|
389 |
+
$arguments = new ArrayExpression([], $line);
|
390 |
foreach ($this->parseArguments() as $n) {
|
391 |
$arguments->addElement($n);
|
392 |
}
|
393 |
|
394 |
+
$node = new MethodCallExpression($alias['node'], $alias['name'], $arguments, $line);
|
395 |
$node->setAttribute('safe', true);
|
396 |
|
397 |
return $node;
|
409 |
$stream = $this->parser->getStream();
|
410 |
$token = $stream->next();
|
411 |
$lineno = $token->getLine();
|
412 |
+
$arguments = new ArrayExpression([], $lineno);
|
413 |
+
$type = Template::ANY_CALL;
|
414 |
if ('.' == $token->getValue()) {
|
415 |
$token = $stream->next();
|
416 |
if (
|
417 |
+
Token::NAME_TYPE == $token->getType()
|
418 |
||
|
419 |
+
Token::NUMBER_TYPE == $token->getType()
|
420 |
||
|
421 |
+
(Token::OPERATOR_TYPE == $token->getType() && preg_match(Lexer::REGEX_NAME, $token->getValue()))
|
422 |
) {
|
423 |
+
$arg = new ConstantExpression($token->getValue(), $lineno);
|
424 |
|
425 |
+
if ($stream->test(Token::PUNCTUATION_TYPE, '(')) {
|
426 |
+
$type = Template::METHOD_CALL;
|
427 |
foreach ($this->parseArguments() as $n) {
|
428 |
$arguments->addElement($n);
|
429 |
}
|
430 |
}
|
431 |
} else {
|
432 |
+
throw new SyntaxError('Expected name or number.', $lineno, $stream->getSourceContext());
|
433 |
}
|
434 |
|
435 |
+
if ($node instanceof NameExpression && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
|
436 |
+
if (!$arg instanceof ConstantExpression) {
|
437 |
+
throw new SyntaxError(sprintf('Dynamic macro names are not supported (called on "%s").', $node->getAttribute('name')), $token->getLine(), $stream->getSourceContext());
|
438 |
}
|
439 |
|
440 |
$name = $arg->getAttribute('value');
|
441 |
|
442 |
if ($this->parser->isReservedMacroName($name)) {
|
443 |
+
throw new SyntaxError(sprintf('"%s" cannot be called as macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext());
|
444 |
}
|
445 |
|
446 |
+
$node = new MethodCallExpression($node, 'get'.$name, $arguments, $lineno);
|
447 |
$node->setAttribute('safe', true);
|
448 |
|
449 |
return $node;
|
450 |
}
|
451 |
} else {
|
452 |
+
$type = Template::ARRAY_CALL;
|
453 |
|
454 |
// slice?
|
455 |
$slice = false;
|
456 |
+
if ($stream->test(Token::PUNCTUATION_TYPE, ':')) {
|
457 |
$slice = true;
|
458 |
+
$arg = new ConstantExpression(0, $token->getLine());
|
459 |
} else {
|
460 |
$arg = $this->parseExpression();
|
461 |
}
|
462 |
|
463 |
+
if ($stream->nextIf(Token::PUNCTUATION_TYPE, ':')) {
|
464 |
$slice = true;
|
465 |
}
|
466 |
|
467 |
if ($slice) {
|
468 |
+
if ($stream->test(Token::PUNCTUATION_TYPE, ']')) {
|
469 |
+
$length = new ConstantExpression(null, $token->getLine());
|
470 |
} else {
|
471 |
$length = $this->parseExpression();
|
472 |
}
|
473 |
|
474 |
$class = $this->getFilterNodeClass('slice', $token->getLine());
|
475 |
+
$arguments = new Node([$arg, $length]);
|
476 |
+
$filter = new $class($node, new ConstantExpression('slice', $token->getLine()), $arguments, $token->getLine());
|
477 |
|
478 |
+
$stream->expect(Token::PUNCTUATION_TYPE, ']');
|
479 |
|
480 |
return $filter;
|
481 |
}
|
482 |
|
483 |
+
$stream->expect(Token::PUNCTUATION_TYPE, ']');
|
484 |
}
|
485 |
|
486 |
+
return new GetAttrExpression($node, $arg, $arguments, $type, $lineno);
|
487 |
}
|
488 |
|
489 |
public function parseFilterExpression($node)
|
496 |
public function parseFilterExpressionRaw($node, $tag = null)
|
497 |
{
|
498 |
while (true) {
|
499 |
+
$token = $this->parser->getStream()->expect(Token::NAME_TYPE);
|
500 |
|
501 |
+
$name = new ConstantExpression($token->getValue(), $token->getLine());
|
502 |
+
if (!$this->parser->getStream()->test(Token::PUNCTUATION_TYPE, '(')) {
|
503 |
+
$arguments = new Node();
|
504 |
} else {
|
505 |
$arguments = $this->parseArguments(true);
|
506 |
}
|
509 |
|
510 |
$node = new $class($node, $name, $arguments, $token->getLine(), $tag);
|
511 |
|
512 |
+
if (!$this->parser->getStream()->test(Token::PUNCTUATION_TYPE, '|')) {
|
513 |
break;
|
514 |
}
|
515 |
|
525 |
* @param bool $namedArguments Whether to allow named arguments or not
|
526 |
* @param bool $definition Whether we are parsing arguments for a function definition
|
527 |
*
|
528 |
+
* @return Node
|
529 |
*
|
530 |
+
* @throws SyntaxError
|
531 |
*/
|
532 |
public function parseArguments($namedArguments = false, $definition = false)
|
533 |
{
|
534 |
$args = [];
|
535 |
$stream = $this->parser->getStream();
|
536 |
|
537 |
+
$stream->expect(Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis');
|
538 |
+
while (!$stream->test(Token::PUNCTUATION_TYPE, ')')) {
|
539 |
if (!empty($args)) {
|
540 |
+
$stream->expect(Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma');
|
541 |
}
|
542 |
|
543 |
if ($definition) {
|
544 |
+
$token = $stream->expect(Token::NAME_TYPE, null, 'An argument must be a name');
|
545 |
+
$value = new NameExpression($token->getValue(), $this->parser->getCurrentToken()->getLine());
|
546 |
} else {
|
547 |
$value = $this->parseExpression();
|
548 |
}
|
549 |
|
550 |
$name = null;
|
551 |
+
if ($namedArguments && $token = $stream->nextIf(Token::OPERATOR_TYPE, '=')) {
|
552 |
+
if (!$value instanceof NameExpression) {
|
553 |
+
throw new SyntaxError(sprintf('A parameter name must be a string, "%s" given.', \get_class($value)), $token->getLine(), $stream->getSourceContext());
|
554 |
}
|
555 |
$name = $value->getAttribute('name');
|
556 |
|
558 |
$value = $this->parsePrimaryExpression();
|
559 |
|
560 |
if (!$this->checkConstantExpression($value)) {
|
561 |
+
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());
|
562 |
}
|
563 |
} else {
|
564 |
$value = $this->parseExpression();
|
568 |
if ($definition) {
|
569 |
if (null === $name) {
|
570 |
$name = $value->getAttribute('name');
|
571 |
+
$value = new ConstantExpression(null, $this->parser->getCurrentToken()->getLine());
|
572 |
}
|
573 |
$args[$name] = $value;
|
574 |
} else {
|
579 |
}
|
580 |
}
|
581 |
}
|
582 |
+
$stream->expect(Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis');
|
583 |
|
584 |
+
return new Node($args);
|
585 |
}
|
586 |
|
587 |
public function parseAssignmentExpression()
|
589 |
$stream = $this->parser->getStream();
|
590 |
$targets = [];
|
591 |
while (true) {
|
592 |
+
$token = $stream->expect(Token::NAME_TYPE, null, 'Only variables can be assigned to');
|
593 |
$value = $token->getValue();
|
594 |
+
if (\in_array(strtolower($value), ['true', 'false', 'none', 'null'])) {
|
595 |
+
throw new SyntaxError(sprintf('You cannot assign a value to "%s".', $value), $token->getLine(), $stream->getSourceContext());
|
596 |
}
|
597 |
+
$targets[] = new AssignNameExpression($value, $token->getLine());
|
598 |
|
599 |
+
if (!$stream->nextIf(Token::PUNCTUATION_TYPE, ',')) {
|
600 |
break;
|
601 |
}
|
602 |
}
|
603 |
|
604 |
+
return new Node($targets);
|
605 |
}
|
606 |
|
607 |
public function parseMultitargetExpression()
|
609 |
$targets = [];
|
610 |
while (true) {
|
611 |
$targets[] = $this->parseExpression();
|
612 |
+
if (!$this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, ',')) {
|
613 |
break;
|
614 |
}
|
615 |
}
|
616 |
|
617 |
+
return new Node($targets);
|
618 |
}
|
619 |
|
620 |
private function parseNotTestExpression(Twig_NodeInterface $node)
|
621 |
{
|
622 |
+
return new NotUnary($this->parseTestExpression($node), $this->parser->getCurrentToken()->getLine());
|
623 |
}
|
624 |
|
625 |
private function parseTestExpression(Twig_NodeInterface $node)
|
629 |
|
630 |
$class = $this->getTestNodeClass($test);
|
631 |
$arguments = null;
|
632 |
+
if ($stream->test(Token::PUNCTUATION_TYPE, '(')) {
|
633 |
$arguments = $this->parser->getExpressionParser()->parseArguments(true);
|
634 |
}
|
635 |
|
639 |
private function getTest($line)
|
640 |
{
|
641 |
$stream = $this->parser->getStream();
|
642 |
+
$name = $stream->expect(Token::NAME_TYPE)->getValue();
|
643 |
|
644 |
if ($test = $this->env->getTest($name)) {
|
645 |
return [$name, $test];
|
646 |
}
|
647 |
|
648 |
+
if ($stream->test(Token::NAME_TYPE)) {
|
649 |
// try 2-words tests
|
650 |
$name = $name.' '.$this->parser->getCurrentToken()->getValue();
|
651 |
|
656 |
}
|
657 |
}
|
658 |
|
659 |
+
$e = new SyntaxError(sprintf('Unknown "%s" test.', $name), $line, $stream->getSourceContext());
|
660 |
$e->addSuggestions($name, array_keys($this->env->getTests()));
|
661 |
|
662 |
throw $e;
|
664 |
|
665 |
private function getTestNodeClass($test)
|
666 |
{
|
667 |
+
if ($test instanceof TwigTest && $test->isDeprecated()) {
|
668 |
$stream = $this->parser->getStream();
|
669 |
$message = sprintf('Twig Test "%s" is deprecated', $test->getName());
|
670 |
+
if (!\is_bool($test->getDeprecatedVersion())) {
|
671 |
$message .= sprintf(' since version %s', $test->getDeprecatedVersion());
|
672 |
}
|
673 |
if ($test->getAlternative()) {
|
679 |
@trigger_error($message, E_USER_DEPRECATED);
|
680 |
}
|
681 |
|
682 |
+
if ($test instanceof TwigTest) {
|
683 |
return $test->getNodeClass();
|
684 |
}
|
685 |
|
689 |
protected function getFunctionNodeClass($name, $line)
|
690 |
{
|
691 |
if (false === $function = $this->env->getFunction($name)) {
|
692 |
+
$e = new SyntaxError(sprintf('Unknown "%s" function.', $name), $line, $this->parser->getStream()->getSourceContext());
|
693 |
$e->addSuggestions($name, array_keys($this->env->getFunctions()));
|
694 |
|
695 |
throw $e;
|
696 |
}
|
697 |
|
698 |
+
if ($function instanceof TwigFunction && $function->isDeprecated()) {
|
699 |
$message = sprintf('Twig Function "%s" is deprecated', $function->getName());
|
700 |
+
if (!\is_bool($function->getDeprecatedVersion())) {
|
701 |
$message .= sprintf(' since version %s', $function->getDeprecatedVersion());
|
702 |
}
|
703 |
if ($function->getAlternative()) {
|
709 |
@trigger_error($message, E_USER_DEPRECATED);
|
710 |
}
|
711 |
|
712 |
+
if ($function instanceof TwigFunction) {
|
713 |
return $function->getNodeClass();
|
714 |
}
|
715 |
|
719 |
protected function getFilterNodeClass($name, $line)
|
720 |
{
|
721 |
if (false === $filter = $this->env->getFilter($name)) {
|
722 |
+
$e = new SyntaxError(sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getStream()->getSourceContext());
|
723 |
$e->addSuggestions($name, array_keys($this->env->getFilters()));
|
724 |
|
725 |
throw $e;
|
726 |
}
|
727 |
|
728 |
+
if ($filter instanceof TwigFilter && $filter->isDeprecated()) {
|
729 |
$message = sprintf('Twig Filter "%s" is deprecated', $filter->getName());
|
730 |
+
if (!\is_bool($filter->getDeprecatedVersion())) {
|
731 |
$message .= sprintf(' since version %s', $filter->getDeprecatedVersion());
|
732 |
}
|
733 |
if ($filter->getAlternative()) {
|
739 |
@trigger_error($message, E_USER_DEPRECATED);
|
740 |
}
|
741 |
|
742 |
+
if ($filter instanceof TwigFilter) {
|
743 |
return $filter->getNodeClass();
|
744 |
}
|
745 |
|
749 |
// checks that the node only contains "constant" elements
|
750 |
protected function checkConstantExpression(Twig_NodeInterface $node)
|
751 |
{
|
752 |
+
if (!($node instanceof ConstantExpression || $node instanceof ArrayExpression
|
753 |
+
|| $node instanceof NegUnary || $node instanceof PosUnary
|
754 |
)) {
|
755 |
return false;
|
756 |
}
|
vendor/twig/twig/lib/Twig/Extension.php
CHANGED
@@ -9,12 +9,15 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
-
|
|
|
|
|
|
|
13 |
{
|
14 |
/**
|
15 |
* @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead
|
16 |
*/
|
17 |
-
public function initRuntime(
|
18 |
{
|
19 |
}
|
20 |
|
@@ -61,7 +64,7 @@ abstract class Twig_Extension implements Twig_ExtensionInterface
|
|
61 |
*/
|
62 |
public function getName()
|
63 |
{
|
64 |
-
return get_class($this);
|
65 |
}
|
66 |
}
|
67 |
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Environment;
|
13 |
+
use Twig\Extension\ExtensionInterface;
|
14 |
+
|
15 |
+
abstract class Twig_Extension implements ExtensionInterface
|
16 |
{
|
17 |
/**
|
18 |
* @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead
|
19 |
*/
|
20 |
+
public function initRuntime(Environment $environment)
|
21 |
{
|
22 |
}
|
23 |
|
64 |
*/
|
65 |
public function getName()
|
66 |
{
|
67 |
+
return \get_class($this);
|
68 |
}
|
69 |
}
|
70 |
|
vendor/twig/twig/lib/Twig/Extension/Core.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
if (
|
4 |
-
define('ENT_SUBSTITUTE', 8);
|
5 |
}
|
6 |
|
7 |
/*
|
@@ -13,10 +13,39 @@ if (!defined('ENT_SUBSTITUTE')) {
|
|
13 |
* file that was distributed with this source code.
|
14 |
*/
|
15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
/**
|
17 |
* @final
|
18 |
*/
|
19 |
-
class Twig_Extension_Core extends
|
20 |
{
|
21 |
protected $dateFormats = ['F j, Y H:i', '%d days'];
|
22 |
protected $numberFormat = [0, '.', ','];
|
@@ -74,22 +103,22 @@ class Twig_Extension_Core extends Twig_Extension
|
|
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;
|
@@ -120,23 +149,23 @@ class Twig_Extension_Core extends Twig_Extension
|
|
120 |
public function getTokenParsers()
|
121 |
{
|
122 |
return [
|
123 |
-
new
|
124 |
-
new
|
125 |
-
new
|
126 |
-
new
|
127 |
-
new
|
128 |
-
new
|
129 |
-
new
|
130 |
-
new
|
131 |
-
new
|
132 |
-
new
|
133 |
-
new
|
134 |
-
new
|
135 |
-
new
|
136 |
-
new
|
137 |
-
new
|
138 |
-
new
|
139 |
-
new
|
140 |
];
|
141 |
}
|
142 |
|
@@ -144,54 +173,54 @@ class Twig_Extension_Core extends Twig_Extension
|
|
144 |
{
|
145 |
$filters = [
|
146 |
// formatting filters
|
147 |
-
new
|
148 |
-
new
|
149 |
-
new
|
150 |
-
new
|
151 |
-
new
|
152 |
-
new
|
153 |
-
new
|
154 |
|
155 |
// encoding
|
156 |
-
new
|
157 |
-
new
|
158 |
-
new
|
159 |
|
160 |
// string filters
|
161 |
-
new
|
162 |
-
new
|
163 |
-
new
|
164 |
-
new
|
165 |
-
new
|
166 |
-
new
|
167 |
-
new
|
168 |
|
169 |
// array helpers
|
170 |
-
new
|
171 |
-
new
|
172 |
-
new
|
173 |
-
new
|
174 |
-
new
|
175 |
|
176 |
// string/array filters
|
177 |
-
new
|
178 |
-
new
|
179 |
-
new
|
180 |
-
new
|
181 |
-
new
|
182 |
|
183 |
// iteration and runtime
|
184 |
-
new
|
185 |
-
new
|
186 |
|
187 |
// escaping
|
188 |
-
new
|
189 |
-
new
|
190 |
];
|
191 |
|
192 |
-
if (function_exists('mb_get_info')) {
|
193 |
-
$filters[] = new
|
194 |
-
$filters[] = new
|
195 |
}
|
196 |
|
197 |
return $filters;
|
@@ -200,33 +229,33 @@ class Twig_Extension_Core extends Twig_Extension
|
|
200 |
public function getFunctions()
|
201 |
{
|
202 |
return [
|
203 |
-
new
|
204 |
-
new
|
205 |
-
new
|
206 |
-
new
|
207 |
-
new
|
208 |
-
new
|
209 |
-
new
|
210 |
-
new
|
211 |
-
new
|
212 |
];
|
213 |
}
|
214 |
|
215 |
public function getTests()
|
216 |
{
|
217 |
return [
|
218 |
-
new
|
219 |
-
new
|
220 |
-
new
|
221 |
-
new
|
222 |
-
new
|
223 |
-
new
|
224 |
-
new
|
225 |
-
new
|
226 |
-
new
|
227 |
-
new
|
228 |
-
new
|
229 |
-
new
|
230 |
];
|
231 |
}
|
232 |
|
@@ -234,39 +263,39 @@ class Twig_Extension_Core extends Twig_Extension
|
|
234 |
{
|
235 |
return [
|
236 |
[
|
237 |
-
'not' => ['precedence' => 50, 'class' => '
|
238 |
-
'-' => ['precedence' => 500, 'class' => '
|
239 |
-
'+' => ['precedence' => 500, 'class' => '
|
240 |
],
|
241 |
[
|
242 |
-
'or' => ['precedence' => 10, 'class' => '
|
243 |
-
'and' => ['precedence' => 15, 'class' => '
|
244 |
-
'b-or' => ['precedence' => 16, 'class' => '
|
245 |
-
'b-xor' => ['precedence' => 17, 'class' => '
|
246 |
-
'b-and' => ['precedence' => 18, 'class' => '
|
247 |
-
'==' => ['precedence' => 20, 'class' => '
|
248 |
-
'!=' => ['precedence' => 20, 'class' => '
|
249 |
-
'<' => ['precedence' => 20, 'class' => '
|
250 |
-
'>' => ['precedence' => 20, 'class' => '
|
251 |
-
'>=' => ['precedence' => 20, 'class' => '
|
252 |
-
'<=' => ['precedence' => 20, 'class' => '
|
253 |
-
'not in' => ['precedence' => 20, 'class' => '
|
254 |
-
'in' => ['precedence' => 20, 'class' => '
|
255 |
-
'matches' => ['precedence' => 20, 'class' => '
|
256 |
-
'starts with' => ['precedence' => 20, 'class' => '
|
257 |
-
'ends with' => ['precedence' => 20, 'class' => '
|
258 |
-
'..' => ['precedence' => 25, 'class' => '
|
259 |
-
'+' => ['precedence' => 30, 'class' => '
|
260 |
-
'-' => ['precedence' => 30, 'class' => '
|
261 |
-
'~' => ['precedence' => 40, 'class' => '
|
262 |
-
'*' => ['precedence' => 60, 'class' => '
|
263 |
-
'/' => ['precedence' => 60, 'class' => '
|
264 |
-
'//' => ['precedence' => 60, 'class' => '
|
265 |
-
'%' => ['precedence' => 60, 'class' => '
|
266 |
-
'is' => ['precedence' => 100, 'associativity' =>
|
267 |
-
'is not' => ['precedence' => 100, 'associativity' =>
|
268 |
-
'**' => ['precedence' => 200, 'class' => '
|
269 |
-
'??' => ['precedence' => 300, 'class' => '
|
270 |
],
|
271 |
];
|
272 |
}
|
@@ -287,23 +316,22 @@ class Twig_Extension_Core extends Twig_Extension
|
|
287 |
*/
|
288 |
function twig_cycle($values, $position)
|
289 |
{
|
290 |
-
if (
|
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
|
304 |
-
* @param Traversable|array|int|float|string $values The values to pick a random item from
|
305 |
*
|
306 |
-
* @throws
|
307 |
*
|
308 |
* @return mixed A random value from the given sequence
|
309 |
*/
|
@@ -313,13 +341,13 @@ function twig_random(Twig_Environment $env, $values = null)
|
|
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 |
}
|
@@ -338,16 +366,16 @@ function twig_random(Twig_Environment $env, $values = null)
|
|
338 |
}
|
339 |
}
|
340 |
} else {
|
341 |
-
return $values[mt_rand(0, strlen($values) - 1)];
|
342 |
}
|
343 |
}
|
344 |
|
345 |
-
if (
|
346 |
return $values;
|
347 |
}
|
348 |
|
349 |
-
if (0 === count($values)) {
|
350 |
-
throw new
|
351 |
}
|
352 |
|
353 |
return $values[array_rand($values, 1)];
|
@@ -356,25 +384,22 @@ function twig_random(Twig_Environment $env, $values = null)
|
|
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
|
364 |
-
* @param
|
365 |
-
* @param string|null
|
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('
|
374 |
-
$format = $date instanceof DateInterval ? $formats[1] : $formats[0];
|
375 |
}
|
376 |
|
377 |
-
if ($date instanceof DateInterval) {
|
378 |
return $date->format($format);
|
379 |
}
|
380 |
|
@@ -384,59 +409,53 @@ function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $
|
|
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
|
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
|
418 |
-
* @param
|
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('
|
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);
|
@@ -446,14 +465,14 @@ function twig_date_converter(Twig_Environment $env, $date = null, $timezone = nu
|
|
446 |
}
|
447 |
|
448 |
if (null === $date || 'now' === $date) {
|
449 |
-
return new DateTime($date, false !== $timezone ? $timezone : $env->getExtension('
|
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('
|
457 |
}
|
458 |
|
459 |
if (false !== $timezone) {
|
@@ -466,22 +485,22 @@ function twig_date_converter(Twig_Environment $env, $date = null, $timezone = nu
|
|
466 |
/**
|
467 |
* Replaces strings within a string.
|
468 |
*
|
469 |
-
* @param string
|
470 |
-
* @param array
|
471 |
-
* @param string|null
|
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 (
|
484 |
-
throw new
|
485 |
}
|
486 |
|
487 |
return strtr($str, $from);
|
@@ -503,7 +522,7 @@ function twig_round($value, $precision = 0, $method = 'common')
|
|
503 |
}
|
504 |
|
505 |
if ('ceil' != $method && 'floor' != $method) {
|
506 |
-
throw new
|
507 |
}
|
508 |
|
509 |
return $method($value * pow(10, $precision)) / pow(10, $precision);
|
@@ -516,17 +535,16 @@ function twig_round($value, $precision = 0, $method = 'common')
|
|
516 |
* be used. Supplying any of the parameters will override the defaults set in the
|
517 |
* environment object.
|
518 |
*
|
519 |
-
* @param
|
520 |
-
* @param
|
521 |
-
* @param
|
522 |
-
* @param string
|
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('
|
530 |
if (null === $decimal) {
|
531 |
$decimal = $defaults[0];
|
532 |
}
|
@@ -551,8 +569,8 @@ function twig_number_format_filter(Twig_Environment $env, $number, $decimal = nu
|
|
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 |
|
@@ -572,9 +590,9 @@ function twig_urlencode_filter($url)
|
|
572 |
*/
|
573 |
function twig_jsonencode_filter($value, $options = 0)
|
574 |
{
|
575 |
-
if ($value instanceof
|
576 |
$value = (string) $value;
|
577 |
-
} elseif (is_array($value)) {
|
578 |
array_walk_recursive($value, '_twig_markup2string');
|
579 |
}
|
580 |
|
@@ -583,7 +601,7 @@ function twig_jsonencode_filter($value, $options = 0)
|
|
583 |
|
584 |
function _twig_markup2string(&$value)
|
585 |
{
|
586 |
-
if ($value instanceof
|
587 |
$value = (string) $value;
|
588 |
}
|
589 |
}
|
@@ -591,31 +609,29 @@ function _twig_markup2string(&$value)
|
|
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
|
603 |
-
* @param 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 (
|
612 |
-
throw new
|
613 |
}
|
614 |
|
615 |
-
if ($arr2 instanceof Traversable) {
|
616 |
$arr2 = iterator_to_array($arr2);
|
617 |
-
} elseif (
|
618 |
-
throw new
|
619 |
}
|
620 |
|
621 |
return array_merge($arr1, $arr2);
|
@@ -624,25 +640,24 @@ function twig_array_merge($arr1, $arr2)
|
|
624 |
/**
|
625 |
* Slices a variable.
|
626 |
*
|
627 |
-
* @param
|
628 |
-
* @param
|
629 |
-
* @param int
|
630 |
-
* @param
|
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 |
}
|
@@ -650,13 +665,13 @@ function twig_slice(Twig_Environment $env, $item, $start, $length = null, $prese
|
|
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 |
|
@@ -666,8 +681,7 @@ function twig_slice(Twig_Environment $env, $item, $start, $length = null, $prese
|
|
666 |
/**
|
667 |
* Returns the first element of the item.
|
668 |
*
|
669 |
-
* @param
|
670 |
-
* @param mixed $item A variable
|
671 |
*
|
672 |
* @return mixed The first element of the item
|
673 |
*/
|
@@ -675,14 +689,13 @@ 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
|
685 |
-
* @param mixed $item A variable
|
686 |
*
|
687 |
* @return mixed The last element of the item
|
688 |
*/
|
@@ -690,7 +703,7 @@ 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 |
/**
|
@@ -698,7 +711,6 @@ function twig_last(Twig_Environment $env, $item)
|
|
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 |
*
|
@@ -707,7 +719,6 @@ function twig_last(Twig_Environment $env, $item)
|
|
707 |
*
|
708 |
* {{ [1, 2, 3]|join }}
|
709 |
* {# returns 123 #}
|
710 |
-
* </pre>
|
711 |
*
|
712 |
* @param array $value An array
|
713 |
* @param string $glue The separator
|
@@ -717,13 +728,13 @@ function twig_last(Twig_Environment $env, $item)
|
|
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 |
|
@@ -732,17 +743,16 @@ function twig_join_filter($value, $glue = '', $and = null)
|
|
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 |
*
|
@@ -754,12 +764,10 @@ function twig_join_filter($value, $glue = '', $and = null)
|
|
754 |
*
|
755 |
* {{ "aabbcc"|split('', 2) }}
|
756 |
* {# returns [aa, bb, cc] #}
|
757 |
-
* </pre>
|
758 |
*
|
759 |
-
* @param
|
760 |
-
* @param string
|
761 |
-
* @param
|
762 |
-
* @param int $limit The limit
|
763 |
*
|
764 |
* @return array The split string as an array
|
765 |
*/
|
@@ -769,7 +777,7 @@ function twig_split_filter(Twig_Environment $env, $value, $delimiter, $limit = n
|
|
769 |
return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit);
|
770 |
}
|
771 |
|
772 |
-
if (
|
773 |
return str_split($value, null === $limit ? 1 : $limit);
|
774 |
}
|
775 |
|
@@ -810,11 +818,9 @@ function _twig_default_filter($value, $default = '')
|
|
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 |
*
|
@@ -822,12 +828,12 @@ function _twig_default_filter($value, $default = '')
|
|
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()) {
|
@@ -846,7 +852,7 @@ function twig_get_array_keys_filter($array)
|
|
846 |
return $keys;
|
847 |
}
|
848 |
|
849 |
-
if (
|
850 |
return [];
|
851 |
}
|
852 |
|
@@ -856,19 +862,18 @@ function twig_get_array_keys_filter($array)
|
|
856 |
/**
|
857 |
* Reverses a variable.
|
858 |
*
|
859 |
-
* @param
|
860 |
-
* @param
|
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 |
|
@@ -896,16 +901,16 @@ function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false
|
|
896 |
/**
|
897 |
* Sorts an array.
|
898 |
*
|
899 |
-
* @param 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 (
|
908 |
-
throw new
|
909 |
}
|
910 |
|
911 |
asort($array);
|
@@ -918,12 +923,12 @@ function twig_sort_filter($array)
|
|
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;
|
@@ -948,7 +953,7 @@ function twig_in_filter($value, $compare)
|
|
948 |
*
|
949 |
* @return string
|
950 |
*
|
951 |
-
* @throws
|
952 |
*/
|
953 |
function twig_trim_filter($string, $characterMask = null, $side = 'both')
|
954 |
{
|
@@ -964,31 +969,30 @@ function twig_trim_filter($string, $characterMask = null, $side = 'both')
|
|
964 |
case 'right':
|
965 |
return rtrim($string, $characterMask);
|
966 |
default:
|
967 |
-
throw new
|
968 |
}
|
969 |
}
|
970 |
|
971 |
/**
|
972 |
* Escapes a string.
|
973 |
*
|
974 |
-
* @param
|
975 |
-
* @param
|
976 |
-
* @param string
|
977 |
-
* @param
|
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
|
985 |
return $string;
|
986 |
}
|
987 |
|
988 |
-
if (
|
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 |
}
|
@@ -1049,7 +1053,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|
1049 |
}
|
1050 |
|
1051 |
if (!preg_match('//u', $string)) {
|
1052 |
-
throw new
|
1053 |
}
|
1054 |
|
1055 |
$string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', '_twig_escape_js_callback', $string);
|
@@ -1066,7 +1070,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|
1066 |
}
|
1067 |
|
1068 |
if (!preg_match('//u', $string)) {
|
1069 |
-
throw new
|
1070 |
}
|
1071 |
|
1072 |
$string = preg_replace_callback('#[^a-zA-Z0-9]#Su', '_twig_escape_css_callback', $string);
|
@@ -1083,7 +1087,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|
1083 |
}
|
1084 |
|
1085 |
if (!preg_match('//u', $string)) {
|
1086 |
-
throw new
|
1087 |
}
|
1088 |
|
1089 |
$string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', '_twig_escape_html_attr_callback', $string);
|
@@ -1101,16 +1105,16 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|
1101 |
static $escapers;
|
1102 |
|
1103 |
if (null === $escapers) {
|
1104 |
-
$escapers = $env->getExtension('
|
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
|
1114 |
}
|
1115 |
}
|
1116 |
|
@@ -1120,7 +1124,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|
1120 |
function twig_escape_filter_is_safe(Twig_Node $filterArgs)
|
1121 |
{
|
1122 |
foreach ($filterArgs as $arg) {
|
1123 |
-
if ($arg instanceof
|
1124 |
return [$arg->getAttribute('value')];
|
1125 |
}
|
1126 |
|
@@ -1130,12 +1134,12 @@ function twig_escape_filter_is_safe(Twig_Node $filterArgs)
|
|
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);
|
@@ -1143,11 +1147,11 @@ if (function_exists('mb_convert_encoding')) {
|
|
1143 |
} else {
|
1144 |
function twig_convert_encoding($string, $to, $from)
|
1145 |
{
|
1146 |
-
throw new
|
1147 |
}
|
1148 |
}
|
1149 |
|
1150 |
-
if (function_exists('mb_ord')) {
|
1151 |
function twig_ord($string)
|
1152 |
{
|
1153 |
return mb_ord($string, 'UTF-8');
|
@@ -1197,7 +1201,7 @@ function _twig_escape_js_callback($matches)
|
|
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 |
|
@@ -1208,7 +1212,7 @@ 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 |
/**
|
@@ -1220,7 +1224,7 @@ function _twig_escape_css_callback($matches)
|
|
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
|
@@ -1234,7 +1238,7 @@ function _twig_escape_html_attr_callback($matches)
|
|
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
|
@@ -1263,16 +1267,15 @@ function _twig_escape_html_attr_callback($matches)
|
|
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
|
1271 |
-
* @param mixed $thing A variable
|
1272 |
*
|
1273 |
* @return int The length of the value
|
1274 |
*/
|
1275 |
-
function twig_length_filter(
|
1276 |
{
|
1277 |
if (null === $thing) {
|
1278 |
return 0;
|
@@ -1283,15 +1286,15 @@ if (function_exists('mb_get_info')) {
|
|
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) {
|
@@ -1304,12 +1307,11 @@ if (function_exists('mb_get_info')) {
|
|
1304 |
/**
|
1305 |
* Converts a string to uppercase.
|
1306 |
*
|
1307 |
-
* @param
|
1308 |
-
* @param string $string A string
|
1309 |
*
|
1310 |
* @return string The uppercased string
|
1311 |
*/
|
1312 |
-
function twig_upper_filter(
|
1313 |
{
|
1314 |
if (null !== $charset = $env->getCharset()) {
|
1315 |
return mb_strtoupper($string, $charset);
|
@@ -1321,12 +1323,11 @@ if (function_exists('mb_get_info')) {
|
|
1321 |
/**
|
1322 |
* Converts a string to lowercase.
|
1323 |
*
|
1324 |
-
* @param
|
1325 |
-
* @param string $string A string
|
1326 |
*
|
1327 |
* @return string The lowercased string
|
1328 |
*/
|
1329 |
-
function twig_lower_filter(
|
1330 |
{
|
1331 |
if (null !== $charset = $env->getCharset()) {
|
1332 |
return mb_strtolower($string, $charset);
|
@@ -1338,12 +1339,11 @@ if (function_exists('mb_get_info')) {
|
|
1338 |
/**
|
1339 |
* Returns a titlecased string.
|
1340 |
*
|
1341 |
-
* @param
|
1342 |
-
* @param string $string A string
|
1343 |
*
|
1344 |
* @return string The titlecased string
|
1345 |
*/
|
1346 |
-
function twig_title_string_filter(
|
1347 |
{
|
1348 |
if (null !== $charset = $env->getCharset()) {
|
1349 |
return mb_convert_case($string, MB_CASE_TITLE, $charset);
|
@@ -1355,12 +1355,11 @@ if (function_exists('mb_get_info')) {
|
|
1355 |
/**
|
1356 |
* Returns a capitalized string.
|
1357 |
*
|
1358 |
-
* @param
|
1359 |
-
* @param string $string A string
|
1360 |
*
|
1361 |
* @return string The capitalized string
|
1362 |
*/
|
1363 |
-
function twig_capitalize_string_filter(
|
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);
|
@@ -1374,31 +1373,30 @@ else {
|
|
1374 |
/**
|
1375 |
* Returns the length of a variable.
|
1376 |
*
|
1377 |
-
* @param
|
1378 |
-
* @param mixed $thing A variable
|
1379 |
*
|
1380 |
* @return int The length of the value
|
1381 |
*/
|
1382 |
-
function twig_length_filter(
|
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) {
|
@@ -1411,12 +1409,11 @@ else {
|
|
1411 |
/**
|
1412 |
* Returns a titlecased string.
|
1413 |
*
|
1414 |
-
* @param
|
1415 |
-
* @param string $string A string
|
1416 |
*
|
1417 |
* @return string The titlecased string
|
1418 |
*/
|
1419 |
-
function twig_title_string_filter(
|
1420 |
{
|
1421 |
return ucwords(strtolower($string));
|
1422 |
}
|
@@ -1424,12 +1421,11 @@ else {
|
|
1424 |
/**
|
1425 |
* Returns a capitalized string.
|
1426 |
*
|
1427 |
-
* @param
|
1428 |
-
* @param string $string A string
|
1429 |
*
|
1430 |
* @return string The capitalized string
|
1431 |
*/
|
1432 |
-
function twig_capitalize_string_filter(
|
1433 |
{
|
1434 |
return ucfirst(strtolower($string));
|
1435 |
}
|
@@ -1440,7 +1436,7 @@ else {
|
|
1440 |
*/
|
1441 |
function twig_ensure_traversable($seq)
|
1442 |
{
|
1443 |
-
if ($seq instanceof Traversable || is_array($seq)) {
|
1444 |
return $seq;
|
1445 |
}
|
1446 |
|
@@ -1450,12 +1446,10 @@ function twig_ensure_traversable($seq)
|
|
1450 |
/**
|
1451 |
* Checks if a variable is empty.
|
1452 |
*
|
1453 |
-
*
|
1454 |
-
*
|
1455 |
-
*
|
1456 |
-
*
|
1457 |
-
* {% endif %}
|
1458 |
-
* </pre>
|
1459 |
*
|
1460 |
* @param mixed $value A variable
|
1461 |
*
|
@@ -1463,11 +1457,11 @@ function twig_ensure_traversable($seq)
|
|
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 |
|
@@ -1477,12 +1471,10 @@ function twig_test_empty($value)
|
|
1477 |
/**
|
1478 |
* Checks if a variable is traversable.
|
1479 |
*
|
1480 |
-
*
|
1481 |
-
*
|
1482 |
-
*
|
1483 |
-
*
|
1484 |
-
* {% endif %}
|
1485 |
-
* </pre>
|
1486 |
*
|
1487 |
* @param mixed $value A variable
|
1488 |
*
|
@@ -1490,19 +1482,18 @@ function twig_test_empty($value)
|
|
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
|
1500 |
-
* @param array
|
1501 |
-
* @param
|
1502 |
-
* @param
|
1503 |
-
* @param bool
|
1504 |
-
* @param bool
|
1505 |
-
* @param bool $sandboxed Whether to sandbox the template or not
|
1506 |
*
|
1507 |
* @return string The rendered template
|
1508 |
*/
|
@@ -1514,8 +1505,8 @@ function twig_include(Twig_Environment $env, $context, $template, $variables = [
|
|
1514 |
$variables = array_merge($context, $variables);
|
1515 |
}
|
1516 |
|
1517 |
-
if ($isSandboxed = $sandboxed && $env->hasExtension('
|
1518 |
-
$sandbox = $env->getExtension('
|
1519 |
if (!$alreadySandboxed = $sandbox->isSandboxed()) {
|
1520 |
$sandbox->enableSandbox();
|
1521 |
}
|
@@ -1524,7 +1515,7 @@ function twig_include(Twig_Environment $env, $context, $template, $variables = [
|
|
1524 |
$result = '';
|
1525 |
try {
|
1526 |
$result = $env->resolveTemplate($template)->render($variables);
|
1527 |
-
} catch (
|
1528 |
if (!$ignoreMissing) {
|
1529 |
if ($isSandboxed && !$alreadySandboxed) {
|
1530 |
$sandbox->disableSandbox();
|
@@ -1532,13 +1523,13 @@ function twig_include(Twig_Environment $env, $context, $template, $variables = [
|
|
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 |
}
|
@@ -1556,9 +1547,8 @@ function twig_include(Twig_Environment $env, $context, $template, $variables = [
|
|
1556 |
/**
|
1557 |
* Returns a template content without rendering it.
|
1558 |
*
|
1559 |
-
* @param
|
1560 |
-
* @param
|
1561 |
-
* @param bool $ignoreMissing Whether to ignore missing templates or not
|
1562 |
*
|
1563 |
* @return string The template source
|
1564 |
*/
|
@@ -1566,12 +1556,12 @@ function twig_source(Twig_Environment $env, $name, $ignoreMissing = false)
|
|
1566 |
{
|
1567 |
$loader = $env->getLoader();
|
1568 |
try {
|
1569 |
-
if (!$loader instanceof
|
1570 |
return $loader->getSource($name);
|
1571 |
} else {
|
1572 |
return $loader->getSourceContext($name)->getCode();
|
1573 |
}
|
1574 |
-
} catch (
|
1575 |
if (!$ignoreMissing) {
|
1576 |
throw $e;
|
1577 |
}
|
@@ -1589,10 +1579,10 @@ function twig_source(Twig_Environment $env, $name, $ignoreMissing = false)
|
|
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 |
/**
|
@@ -1606,10 +1596,10 @@ function twig_constant($constant, $object = null)
|
|
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 |
/**
|
@@ -1623,7 +1613,7 @@ function twig_constant_is_defined($constant, $object = null)
|
|
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 |
|
@@ -1632,8 +1622,8 @@ function twig_array_batch($items, $size, $fill = null)
|
|
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)
|
1 |
<?php
|
2 |
|
3 |
+
if (!\defined('ENT_SUBSTITUTE')) {
|
4 |
+
\define('ENT_SUBSTITUTE', 8);
|
5 |
}
|
6 |
|
7 |
/*
|
13 |
* file that was distributed with this source code.
|
14 |
*/
|
15 |
|
16 |
+
use Twig\Environment;
|
17 |
+
use Twig\Error\LoaderError;
|
18 |
+
use Twig\Error\RuntimeError;
|
19 |
+
use Twig\ExpressionParser;
|
20 |
+
use Twig\Extension\AbstractExtension;
|
21 |
+
use Twig\Loader\SourceContextLoaderInterface;
|
22 |
+
use Twig\Markup;
|
23 |
+
use Twig\Node\Expression\ConstantExpression;
|
24 |
+
use Twig\TokenParser\BlockTokenParser;
|
25 |
+
use Twig\TokenParser\DeprecatedTokenParser;
|
26 |
+
use Twig\TokenParser\DoTokenParser;
|
27 |
+
use Twig\TokenParser\EmbedTokenParser;
|
28 |
+
use Twig\TokenParser\ExtendsTokenParser;
|
29 |
+
use Twig\TokenParser\FilterTokenParser;
|
30 |
+
use Twig\TokenParser\FlushTokenParser;
|
31 |
+
use Twig\TokenParser\ForTokenParser;
|
32 |
+
use Twig\TokenParser\FromTokenParser;
|
33 |
+
use Twig\TokenParser\IfTokenParser;
|
34 |
+
use Twig\TokenParser\ImportTokenParser;
|
35 |
+
use Twig\TokenParser\IncludeTokenParser;
|
36 |
+
use Twig\TokenParser\MacroTokenParser;
|
37 |
+
use Twig\TokenParser\SetTokenParser;
|
38 |
+
use Twig\TokenParser\SpacelessTokenParser;
|
39 |
+
use Twig\TokenParser\UseTokenParser;
|
40 |
+
use Twig\TokenParser\WithTokenParser;
|
41 |
+
use Twig\TwigFilter;
|
42 |
+
use Twig\TwigFunction;
|
43 |
+
use Twig\TwigTest;
|
44 |
+
|
45 |
/**
|
46 |
* @final
|
47 |
*/
|
48 |
+
class Twig_Extension_Core extends AbstractExtension
|
49 |
{
|
50 |
protected $dateFormats = ['F j, Y H:i', '%d days'];
|
51 |
protected $numberFormat = [0, '.', ','];
|
103 |
/**
|
104 |
* Sets the default timezone to be used by the date filter.
|
105 |
*
|
106 |
+
* @param \DateTimeZone|string $timezone The default timezone string or a \DateTimeZone object
|
107 |
*/
|
108 |
public function setTimezone($timezone)
|
109 |
{
|
110 |
+
$this->timezone = $timezone instanceof \DateTimeZone ? $timezone : new \DateTimeZone($timezone);
|
111 |
}
|
112 |
|
113 |
/**
|
114 |
* Gets the default timezone to be used by the date filter.
|
115 |
*
|
116 |
+
* @return \DateTimeZone The default timezone currently in use
|
117 |
*/
|
118 |
public function getTimezone()
|
119 |
{
|
120 |
if (null === $this->timezone) {
|
121 |
+
$this->timezone = new \DateTimeZone(date_default_timezone_get());
|
122 |
}
|
123 |
|
124 |
return $this->timezone;
|
149 |
public function getTokenParsers()
|
150 |
{
|
151 |
return [
|
152 |
+
new ForTokenParser(),
|
153 |
+
new IfTokenParser(),
|
154 |
+
new ExtendsTokenParser(),
|
155 |
+
new IncludeTokenParser(),
|
156 |
+
new BlockTokenParser(),
|
157 |
+
new UseTokenParser(),
|
158 |
+
new FilterTokenParser(),
|
159 |
+
new MacroTokenParser(),
|
160 |
+
new ImportTokenParser(),
|
161 |
+
new FromTokenParser(),
|
162 |
+
new SetTokenParser(),
|
163 |
+
new SpacelessTokenParser(),
|
164 |
+
new FlushTokenParser(),
|
165 |
+
new DoTokenParser(),
|
166 |
+
new EmbedTokenParser(),
|
167 |
+
new WithTokenParser(),
|
168 |
+
new DeprecatedTokenParser(),
|
169 |
];
|
170 |
}
|
171 |
|
173 |
{
|
174 |
$filters = [
|
175 |
// formatting filters
|
176 |
+
new TwigFilter('date', 'twig_date_format_filter', ['needs_environment' => true]),
|
177 |
+
new TwigFilter('date_modify', 'twig_date_modify_filter', ['needs_environment' => true]),
|
178 |
+
new TwigFilter('format', 'sprintf'),
|
179 |
+
new TwigFilter('replace', 'twig_replace_filter'),
|
180 |
+
new TwigFilter('number_format', 'twig_number_format_filter', ['needs_environment' => true]),
|
181 |
+
new TwigFilter('abs', 'abs'),
|
182 |
+
new TwigFilter('round', 'twig_round'),
|
183 |
|
184 |
// encoding
|
185 |
+
new TwigFilter('url_encode', 'twig_urlencode_filter'),
|
186 |
+
new TwigFilter('json_encode', 'twig_jsonencode_filter'),
|
187 |
+
new TwigFilter('convert_encoding', 'twig_convert_encoding'),
|
188 |
|
189 |
// string filters
|
190 |
+
new TwigFilter('title', 'twig_title_string_filter', ['needs_environment' => true]),
|
191 |
+
new TwigFilter('capitalize', 'twig_capitalize_string_filter', ['needs_environment' => true]),
|
192 |
+
new TwigFilter('upper', 'strtoupper'),
|
193 |
+
new TwigFilter('lower', 'strtolower'),
|
194 |
+
new TwigFilter('striptags', 'strip_tags'),
|
195 |
+
new TwigFilter('trim', 'twig_trim_filter'),
|
196 |
+
new TwigFilter('nl2br', 'nl2br', ['pre_escape' => 'html', 'is_safe' => ['html']]),
|
197 |
|
198 |
// array helpers
|
199 |
+
new TwigFilter('join', 'twig_join_filter'),
|
200 |
+
new TwigFilter('split', 'twig_split_filter', ['needs_environment' => true]),
|
201 |
+
new TwigFilter('sort', 'twig_sort_filter'),
|
202 |
+
new TwigFilter('merge', 'twig_array_merge'),
|
203 |
+
new TwigFilter('batch', 'twig_array_batch'),
|
204 |
|
205 |
// string/array filters
|
206 |
+
new TwigFilter('reverse', 'twig_reverse_filter', ['needs_environment' => true]),
|
207 |
+
new TwigFilter('length', 'twig_length_filter', ['needs_environment' => true]),
|
208 |
+
new TwigFilter('slice', 'twig_slice', ['needs_environment' => true]),
|
209 |
+
new TwigFilter('first', 'twig_first', ['needs_environment' => true]),
|
210 |
+
new TwigFilter('last', 'twig_last', ['needs_environment' => true]),
|
211 |
|
212 |
// iteration and runtime
|
213 |
+
new TwigFilter('default', '_twig_default_filter', ['node_class' => '\Twig\Node\Expression\Filter\DefaultFilter']),
|
214 |
+
new TwigFilter('keys', 'twig_get_array_keys_filter'),
|
215 |
|
216 |
// escaping
|
217 |
+
new TwigFilter('escape', 'twig_escape_filter', ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']),
|
218 |
+
new TwigFilter('e', 'twig_escape_filter', ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']),
|
219 |
];
|
220 |
|
221 |
+
if (\function_exists('mb_get_info')) {
|
222 |
+
$filters[] = new TwigFilter('upper', 'twig_upper_filter', ['needs_environment' => true]);
|
223 |
+
$filters[] = new TwigFilter('lower', 'twig_lower_filter', ['needs_environment' => true]);
|
224 |
}
|
225 |
|
226 |
return $filters;
|
229 |
public function getFunctions()
|
230 |
{
|
231 |
return [
|
232 |
+
new TwigFunction('max', 'max'),
|
233 |
+
new TwigFunction('min', 'min'),
|
234 |
+
new TwigFunction('range', 'range'),
|
235 |
+
new TwigFunction('constant', 'twig_constant'),
|
236 |
+
new TwigFunction('cycle', 'twig_cycle'),
|
237 |
+
new TwigFunction('random', 'twig_random', ['needs_environment' => true]),
|
238 |
+
new TwigFunction('date', 'twig_date_converter', ['needs_environment' => true]),
|
239 |
+
new TwigFunction('include', 'twig_include', ['needs_environment' => true, 'needs_context' => true, 'is_safe' => ['all']]),
|
240 |
+
new TwigFunction('source', 'twig_source', ['needs_environment' => true, 'is_safe' => ['all']]),
|
241 |
];
|
242 |
}
|
243 |
|
244 |
public function getTests()
|
245 |
{
|
246 |
return [
|
247 |
+
new TwigTest('even', null, ['node_class' => '\Twig\Node\Expression\Test\EvenTest']),
|
248 |
+
new TwigTest('odd', null, ['node_class' => '\Twig\Node\Expression\Test\OddTest']),
|
249 |
+
new TwigTest('defined', null, ['node_class' => '\Twig\Node\Expression\Test\DefinedTest']),
|
250 |
+
new TwigTest('sameas', null, ['node_class' => '\Twig\Node\Expression\Test\SameasTest', 'deprecated' => '1.21', 'alternative' => 'same as']),
|
251 |
+
new TwigTest('same as', null, ['node_class' => '\Twig\Node\Expression\Test\SameasTest']),
|
252 |
+
new TwigTest('none', null, ['node_class' => '\Twig\Node\Expression\Test\NullTest']),
|
253 |
+
new TwigTest('null', null, ['node_class' => '\Twig\Node\Expression\Test\NullTest']),
|
254 |
+
new TwigTest('divisibleby', null, ['node_class' => '\Twig\Node\Expression\Test\DivisiblebyTest', 'deprecated' => '1.21', 'alternative' => 'divisible by']),
|
255 |
+
new TwigTest('divisible by', null, ['node_class' => '\Twig\Node\Expression\Test\DivisiblebyTest']),
|
256 |
+
new TwigTest('constant', null, ['node_class' => '\Twig\Node\Expression\Test\ConstantTest']),
|
257 |
+
new TwigTest('empty', 'twig_test_empty'),
|
258 |
+
new TwigTest('iterable', 'twig_test_iterable'),
|
259 |
];
|
260 |
}
|
261 |
|
263 |
{
|
264 |
return [
|
265 |
[
|
266 |
+
'not' => ['precedence' => 50, 'class' => '\Twig\Node\Expression\Unary\NotUnary'],
|
267 |
+
'-' => ['precedence' => 500, 'class' => '\Twig\Node\Expression\Unary\NegUnary'],
|
268 |
+
'+' => ['precedence' => 500, 'class' => '\Twig\Node\Expression\Unary\PosUnary'],
|
269 |
],
|
270 |
[
|
271 |
+
'or' => ['precedence' => 10, 'class' => '\Twig\Node\Expression\Binary\OrBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
272 |
+
'and' => ['precedence' => 15, 'class' => '\Twig\Node\Expression\Binary\AndBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
273 |
+
'b-or' => ['precedence' => 16, 'class' => '\Twig\Node\Expression\Binary\BitwiseOrBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
274 |
+
'b-xor' => ['precedence' => 17, 'class' => '\Twig\Node\Expression\Binary\BitwiseXorBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
275 |
+
'b-and' => ['precedence' => 18, 'class' => '\Twig\Node\Expression\Binary\BitwiseAndBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
276 |
+
'==' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\EqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
277 |
+
'!=' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\NotEqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
278 |
+
'<' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\LessBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
279 |
+
'>' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\GreaterBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
280 |
+
'>=' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\GreaterEqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
281 |
+
'<=' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\LessEqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
282 |
+
'not in' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\NotInBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
283 |
+
'in' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\InBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
284 |
+
'matches' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\MatchesBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
285 |
+
'starts with' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\StartsWithBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
286 |
+
'ends with' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\EndsWithBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
287 |
+
'..' => ['precedence' => 25, 'class' => '\Twig\Node\Expression\Binary\RangeBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
288 |
+
'+' => ['precedence' => 30, 'class' => '\Twig\Node\Expression\Binary\AddBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
289 |
+
'-' => ['precedence' => 30, 'class' => '\Twig\Node\Expression\Binary\SubBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
290 |
+
'~' => ['precedence' => 40, 'class' => '\Twig\Node\Expression\Binary\ConcatBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
291 |
+
'*' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\MulBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
292 |
+
'/' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\DivBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
293 |
+
'//' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\FloorDivBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
294 |
+
'%' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\ModBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
295 |
+
'is' => ['precedence' => 100, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
296 |
+
'is not' => ['precedence' => 100, 'associativity' => ExpressionParser::OPERATOR_LEFT],
|
297 |
+
'**' => ['precedence' => 200, 'class' => '\Twig\Node\Expression\Binary\PowerBinary', 'associativity' => ExpressionParser::OPERATOR_RIGHT],
|
298 |
+
'??' => ['precedence' => 300, 'class' => '\Twig\Node\Expression\NullCoalesceExpression', 'associativity' => ExpressionParser::OPERATOR_RIGHT],
|
299 |
],
|
300 |
];
|
301 |
}
|
316 |
*/
|
317 |
function twig_cycle($values, $position)
|
318 |
{
|
319 |
+
if (!\is_array($values) && !$values instanceof ArrayAccess) {
|
320 |
return $values;
|
321 |
}
|
322 |
|
323 |
+
return $values[$position % \count($values)];
|
324 |
}
|
325 |
|
326 |
/**
|
327 |
* Returns a random value depending on the supplied parameter type:
|
328 |
+
* - a random item from a \Traversable or array
|
329 |
* - a random character from a string
|
330 |
* - a random integer between 0 and the integer parameter.
|
331 |
*
|
332 |
+
* @param \Traversable|array|int|float|string $values The values to pick a random item from
|
|
|
333 |
*
|
334 |
+
* @throws RuntimeError when $values is an empty array (does not apply to an empty string which is returned as is)
|
335 |
*
|
336 |
* @return mixed A random value from the given sequence
|
337 |
*/
|
341 |
return mt_rand();
|
342 |
}
|
343 |
|
344 |
+
if (\is_int($values) || \is_float($values)) {
|
345 |
return $values < 0 ? mt_rand($values, 0) : mt_rand(0, $values);
|
346 |
}
|
347 |
|
348 |
+
if ($values instanceof \Traversable) {
|
349 |
$values = iterator_to_array($values);
|
350 |
+
} elseif (\is_string($values)) {
|
351 |
if ('' === $values) {
|
352 |
return '';
|
353 |
}
|
366 |
}
|
367 |
}
|
368 |
} else {
|
369 |
+
return $values[mt_rand(0, \strlen($values) - 1)];
|
370 |
}
|
371 |
}
|
372 |
|
373 |
+
if (!\is_array($values)) {
|
374 |
return $values;
|
375 |
}
|
376 |
|
377 |
+
if (0 === \count($values)) {
|
378 |
+
throw new RuntimeError('The random function cannot pick from an empty array.');
|
379 |
}
|
380 |
|
381 |
return $values[array_rand($values, 1)];
|
384 |
/**
|
385 |
* Converts a date to the given format.
|
386 |
*
|
|
|
387 |
* {{ post.published_at|date("m/d/Y") }}
|
|
|
388 |
*
|
389 |
+
* @param \DateTime|\DateTimeInterface|\DateInterval|string $date A date
|
390 |
+
* @param string|null $format The target format, null to use the default
|
391 |
+
* @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged
|
|
|
392 |
*
|
393 |
* @return string The formatted date
|
394 |
*/
|
395 |
function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $timezone = null)
|
396 |
{
|
397 |
if (null === $format) {
|
398 |
+
$formats = $env->getExtension('\Twig\Extension\CoreExtension')->getDateFormat();
|
399 |
+
$format = $date instanceof \DateInterval ? $formats[1] : $formats[0];
|
400 |
}
|
401 |
|
402 |
+
if ($date instanceof \DateInterval) {
|
403 |
return $date->format($format);
|
404 |
}
|
405 |
|
409 |
/**
|
410 |
* Returns a new date object modified.
|
411 |
*
|
|
|
412 |
* {{ post.published_at|date_modify("-1day")|date("m/d/Y") }}
|
|
|
413 |
*
|
414 |
+
* @param \DateTime|string $date A date
|
|
|
415 |
* @param string $modifier A modifier string
|
416 |
*
|
417 |
+
* @return \DateTime A new date object
|
418 |
*/
|
419 |
function twig_date_modify_filter(Twig_Environment $env, $date, $modifier)
|
420 |
{
|
421 |
$date = twig_date_converter($env, $date, false);
|
422 |
$resultDate = $date->modify($modifier);
|
423 |
|
424 |
+
// This is a hack to ensure PHP 5.2 support and support for \DateTimeImmutable
|
425 |
+
// \DateTime::modify does not return the modified \DateTime object < 5.3.0
|
426 |
+
// and \DateTimeImmutable does not modify $date.
|
427 |
return null === $resultDate ? $date : $resultDate;
|
428 |
}
|
429 |
|
430 |
/**
|
431 |
+
* Converts an input to a \DateTime instance.
|
432 |
*
|
|
|
433 |
* {% if date(user.created_at) < date('+2days') %}
|
434 |
* {# do something #}
|
435 |
* {% endif %}
|
|
|
436 |
*
|
437 |
+
* @param \DateTime|\DateTimeInterface|string|null $date A date
|
438 |
+
* @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged
|
|
|
439 |
*
|
440 |
+
* @return \DateTime A \DateTime instance
|
441 |
*/
|
442 |
function twig_date_converter(Twig_Environment $env, $date = null, $timezone = null)
|
443 |
{
|
444 |
// determine the timezone
|
445 |
if (false !== $timezone) {
|
446 |
if (null === $timezone) {
|
447 |
+
$timezone = $env->getExtension('\Twig\Extension\CoreExtension')->getTimezone();
|
448 |
+
} elseif (!$timezone instanceof \DateTimeZone) {
|
449 |
+
$timezone = new \DateTimeZone($timezone);
|
450 |
}
|
451 |
}
|
452 |
|
453 |
// immutable dates
|
454 |
+
if ($date instanceof \DateTimeImmutable) {
|
455 |
return false !== $timezone ? $date->setTimezone($timezone) : $date;
|
456 |
}
|
457 |
|
458 |
+
if ($date instanceof \DateTime || $date instanceof \DateTimeInterface) {
|
459 |
$date = clone $date;
|
460 |
if (false !== $timezone) {
|
461 |
$date->setTimezone($timezone);
|
465 |
}
|
466 |
|
467 |
if (null === $date || 'now' === $date) {
|
468 |
+
return new \DateTime($date, false !== $timezone ? $timezone : $env->getExtension('\Twig\Extension\CoreExtension')->getTimezone());
|
469 |
}
|
470 |
|
471 |
$asString = (string) $date;
|
472 |
if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) {
|
473 |
+
$date = new \DateTime('@'.$date);
|
474 |
} else {
|
475 |
+
$date = new \DateTime($date, $env->getExtension('\Twig\Extension\CoreExtension')->getTimezone());
|
476 |
}
|
477 |
|
478 |
if (false !== $timezone) {
|
485 |
/**
|
486 |
* Replaces strings within a string.
|
487 |
*
|
488 |
+
* @param string $str String to replace in
|
489 |
+
* @param array|\Traversable $from Replace values
|
490 |
+
* @param string|null $to Replace to, deprecated (@see https://secure.php.net/manual/en/function.strtr.php)
|
491 |
*
|
492 |
* @return string
|
493 |
*/
|
494 |
function twig_replace_filter($str, $from, $to = null)
|
495 |
{
|
496 |
+
if ($from instanceof \Traversable) {
|
497 |
$from = iterator_to_array($from);
|
498 |
+
} elseif (\is_string($from) && \is_string($to)) {
|
499 |
@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);
|
500 |
|
501 |
return strtr($str, $from, $to);
|
502 |
+
} elseif (!\is_array($from)) {
|
503 |
+
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)));
|
504 |
}
|
505 |
|
506 |
return strtr($str, $from);
|
522 |
}
|
523 |
|
524 |
if ('ceil' != $method && 'floor' != $method) {
|
525 |
+
throw new RuntimeError('The round filter only supports the "common", "ceil", and "floor" methods.');
|
526 |
}
|
527 |
|
528 |
return $method($value * pow(10, $precision)) / pow(10, $precision);
|
535 |
* be used. Supplying any of the parameters will override the defaults set in the
|
536 |
* environment object.
|
537 |
*
|
538 |
+
* @param mixed $number A float/int/string of the number to format
|
539 |
+
* @param int $decimal the number of decimal points to display
|
540 |
+
* @param string $decimalPoint the character(s) to use for the decimal point
|
541 |
+
* @param string $thousandSep the character(s) to use for the thousands separator
|
|
|
542 |
*
|
543 |
* @return string The formatted number
|
544 |
*/
|
545 |
function twig_number_format_filter(Twig_Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null)
|
546 |
{
|
547 |
+
$defaults = $env->getExtension('\Twig\Extension\CoreExtension')->getNumberFormat();
|
548 |
if (null === $decimal) {
|
549 |
$decimal = $defaults[0];
|
550 |
}
|
569 |
*/
|
570 |
function twig_urlencode_filter($url)
|
571 |
{
|
572 |
+
if (\is_array($url)) {
|
573 |
+
if (\defined('PHP_QUERY_RFC3986')) {
|
574 |
return http_build_query($url, '', '&', PHP_QUERY_RFC3986);
|
575 |
}
|
576 |
|
590 |
*/
|
591 |
function twig_jsonencode_filter($value, $options = 0)
|
592 |
{
|
593 |
+
if ($value instanceof Markup) {
|
594 |
$value = (string) $value;
|
595 |
+
} elseif (\is_array($value)) {
|
596 |
array_walk_recursive($value, '_twig_markup2string');
|
597 |
}
|
598 |
|
601 |
|
602 |
function _twig_markup2string(&$value)
|
603 |
{
|
604 |
+
if ($value instanceof Markup) {
|
605 |
$value = (string) $value;
|
606 |
}
|
607 |
}
|
609 |
/**
|
610 |
* Merges an array with another one.
|
611 |
*
|
|
|
612 |
* {% set items = { 'apple': 'fruit', 'orange': 'fruit' } %}
|
613 |
*
|
614 |
* {% set items = items|merge({ 'peugeot': 'car' }) %}
|
615 |
*
|
616 |
* {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #}
|
|
|
617 |
*
|
618 |
+
* @param array|\Traversable $arr1 An array
|
619 |
+
* @param array|\Traversable $arr2 An array
|
620 |
*
|
621 |
* @return array The merged array
|
622 |
*/
|
623 |
function twig_array_merge($arr1, $arr2)
|
624 |
{
|
625 |
+
if ($arr1 instanceof \Traversable) {
|
626 |
$arr1 = iterator_to_array($arr1);
|
627 |
+
} elseif (!\is_array($arr1)) {
|
628 |
+
throw new RuntimeError(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as first argument.', \gettype($arr1)));
|
629 |
}
|
630 |
|
631 |
+
if ($arr2 instanceof \Traversable) {
|
632 |
$arr2 = iterator_to_array($arr2);
|
633 |
+
} elseif (!\is_array($arr2)) {
|
634 |
+
throw new RuntimeError(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as second argument.', \gettype($arr2)));
|
635 |
}
|
636 |
|
637 |
return array_merge($arr1, $arr2);
|
640 |
/**
|
641 |
* Slices a variable.
|
642 |
*
|
643 |
+
* @param mixed $item A variable
|
644 |
+
* @param int $start Start of the slice
|
645 |
+
* @param int $length Size of the slice
|
646 |
+
* @param bool $preserveKeys Whether to preserve key or not (when the input is an array)
|
|
|
647 |
*
|
648 |
* @return mixed The sliced variable
|
649 |
*/
|
650 |
function twig_slice(Twig_Environment $env, $item, $start, $length = null, $preserveKeys = false)
|
651 |
{
|
652 |
+
if ($item instanceof \Traversable) {
|
653 |
+
while ($item instanceof \IteratorAggregate) {
|
654 |
$item = $item->getIterator();
|
655 |
}
|
656 |
|
657 |
+
if ($start >= 0 && $length >= 0 && $item instanceof \Iterator) {
|
658 |
try {
|
659 |
+
return iterator_to_array(new \LimitIterator($item, $start, null === $length ? -1 : $length), $preserveKeys);
|
660 |
+
} catch (\OutOfBoundsException $exception) {
|
661 |
return [];
|
662 |
}
|
663 |
}
|
665 |
$item = iterator_to_array($item, $preserveKeys);
|
666 |
}
|
667 |
|
668 |
+
if (\is_array($item)) {
|
669 |
+
return \array_slice($item, $start, $length, $preserveKeys);
|
670 |
}
|
671 |
|
672 |
$item = (string) $item;
|
673 |
|
674 |
+
if (\function_exists('mb_get_info') && null !== $charset = $env->getCharset()) {
|
675 |
return (string) mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset);
|
676 |
}
|
677 |
|
681 |
/**
|
682 |
* Returns the first element of the item.
|
683 |
*
|
684 |
+
* @param mixed $item A variable
|
|
|
685 |
*
|
686 |
* @return mixed The first element of the item
|
687 |
*/
|
689 |
{
|
690 |
$elements = twig_slice($env, $item, 0, 1, false);
|
691 |
|
692 |
+
return \is_string($elements) ? $elements : current($elements);
|
693 |
}
|
694 |
|
695 |
/**
|
696 |
* Returns the last element of the item.
|
697 |
*
|
698 |
+
* @param mixed $item A variable
|
|
|
699 |
*
|
700 |
* @return mixed The last element of the item
|
701 |
*/
|
703 |
{
|
704 |
$elements = twig_slice($env, $item, -1, 1, false);
|
705 |
|
706 |
+
return \is_string($elements) ? $elements : current($elements);
|
707 |
}
|
708 |
|
709 |
/**
|
711 |
*
|
712 |
* The separators between elements are empty strings per default, you can define them with the optional parameters.
|
713 |
*
|
|
|
714 |
* {{ [1, 2, 3]|join(', ', ' and ') }}
|
715 |
* {# returns 1, 2 and 3 #}
|
716 |
*
|
719 |
*
|
720 |
* {{ [1, 2, 3]|join }}
|
721 |
* {# returns 123 #}
|
|
|
722 |
*
|
723 |
* @param array $value An array
|
724 |
* @param string $glue The separator
|
728 |
*/
|
729 |
function twig_join_filter($value, $glue = '', $and = null)
|
730 |
{
|
731 |
+
if ($value instanceof \Traversable) {
|
732 |
$value = iterator_to_array($value, false);
|
733 |
} else {
|
734 |
$value = (array) $value;
|
735 |
}
|
736 |
|
737 |
+
if (0 === \count($value)) {
|
738 |
return '';
|
739 |
}
|
740 |
|
743 |
}
|
744 |
|
745 |
$v = array_values($value);
|
746 |
+
if (1 === \count($v)) {
|
747 |
return $v[0];
|
748 |
}
|
749 |
|
750 |
+
return implode($glue, \array_slice($value, 0, -1)).$and.$v[\count($v) - 1];
|
751 |
}
|
752 |
|
753 |
/**
|
754 |
* Splits the string into an array.
|
755 |
*
|
|
|
756 |
* {{ "one,two,three"|split(',') }}
|
757 |
* {# returns [one, two, three] #}
|
758 |
*
|
764 |
*
|
765 |
* {{ "aabbcc"|split('', 2) }}
|
766 |
* {# returns [aa, bb, cc] #}
|
|
|
767 |
*
|
768 |
+
* @param string $value A string
|
769 |
+
* @param string $delimiter The delimiter
|
770 |
+
* @param int $limit The limit
|
|
|
771 |
*
|
772 |
* @return array The split string as an array
|
773 |
*/
|
777 |
return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit);
|
778 |
}
|
779 |
|
780 |
+
if (!\function_exists('mb_get_info') || null === $charset = $env->getCharset()) {
|
781 |
return str_split($value, null === $limit ? 1 : $limit);
|
782 |
}
|
783 |
|
818 |
*
|
819 |
* It is useful when you want to iterate over the keys of an array:
|
820 |
*
|
|
|
821 |
* {% for key in array|keys %}
|
822 |
* {# ... #}
|
823 |
* {% endfor %}
|
|
|
824 |
*
|
825 |
* @param array $array An array
|
826 |
*
|
828 |
*/
|
829 |
function twig_get_array_keys_filter($array)
|
830 |
{
|
831 |
+
if ($array instanceof \Traversable) {
|
832 |
+
while ($array instanceof \IteratorAggregate) {
|
833 |
$array = $array->getIterator();
|
834 |
}
|
835 |
|
836 |
+
if ($array instanceof \Iterator) {
|
837 |
$keys = [];
|
838 |
$array->rewind();
|
839 |
while ($array->valid()) {
|
852 |
return $keys;
|
853 |
}
|
854 |
|
855 |
+
if (!\is_array($array)) {
|
856 |
return [];
|
857 |
}
|
858 |
|
862 |
/**
|
863 |
* Reverses a variable.
|
864 |
*
|
865 |
+
* @param array|\Traversable|string $item An array, a \Traversable instance, or a string
|
866 |
+
* @param bool $preserveKeys Whether to preserve key or not
|
|
|
867 |
*
|
868 |
* @return mixed The reversed input
|
869 |
*/
|
870 |
function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false)
|
871 |
{
|
872 |
+
if ($item instanceof \Traversable) {
|
873 |
return array_reverse(iterator_to_array($item), $preserveKeys);
|
874 |
}
|
875 |
|
876 |
+
if (\is_array($item)) {
|
877 |
return array_reverse($item, $preserveKeys);
|
878 |
}
|
879 |
|
901 |
/**
|
902 |
* Sorts an array.
|
903 |
*
|
904 |
+
* @param array|\Traversable $array
|
905 |
*
|
906 |
* @return array
|
907 |
*/
|
908 |
function twig_sort_filter($array)
|
909 |
{
|
910 |
+
if ($array instanceof \Traversable) {
|
911 |
$array = iterator_to_array($array);
|
912 |
+
} elseif (!\is_array($array)) {
|
913 |
+
throw new RuntimeError(sprintf('The sort filter only works with arrays or "Traversable", got "%s".', \gettype($array)));
|
914 |
}
|
915 |
|
916 |
asort($array);
|
923 |
*/
|
924 |
function twig_in_filter($value, $compare)
|
925 |
{
|
926 |
+
if (\is_array($compare)) {
|
927 |
+
return \in_array($value, $compare, \is_object($value) || \is_resource($value));
|
928 |
+
} elseif (\is_string($compare) && (\is_string($value) || \is_int($value) || \is_float($value))) {
|
929 |
return '' === $value || false !== strpos($compare, (string) $value);
|
930 |
+
} elseif ($compare instanceof \Traversable) {
|
931 |
+
if (\is_object($value) || \is_resource($value)) {
|
932 |
foreach ($compare as $item) {
|
933 |
if ($item === $value) {
|
934 |
return true;
|
953 |
*
|
954 |
* @return string
|
955 |
*
|
956 |
+
* @throws RuntimeError When an invalid trimming side is used (not a string or not 'left', 'right', or 'both')
|
957 |
*/
|
958 |
function twig_trim_filter($string, $characterMask = null, $side = 'both')
|
959 |
{
|
969 |
case 'right':
|
970 |
return rtrim($string, $characterMask);
|
971 |
default:
|
972 |
+
throw new RuntimeError('Trimming side must be "left", "right" or "both".');
|
973 |
}
|
974 |
}
|
975 |
|
976 |
/**
|
977 |
* Escapes a string.
|
978 |
*
|
979 |
+
* @param mixed $string The value to be escaped
|
980 |
+
* @param string $strategy The escaping strategy
|
981 |
+
* @param string $charset The charset
|
982 |
+
* @param bool $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false)
|
|
|
983 |
*
|
984 |
* @return string
|
985 |
*/
|
986 |
function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
|
987 |
{
|
988 |
+
if ($autoescape && $string instanceof Markup) {
|
989 |
return $string;
|
990 |
}
|
991 |
|
992 |
+
if (!\is_string($string)) {
|
993 |
+
if (\is_object($string) && method_exists($string, '__toString')) {
|
994 |
$string = (string) $string;
|
995 |
+
} elseif (\in_array($strategy, ['html', 'js', 'css', 'html_attr', 'url'])) {
|
996 |
return $string;
|
997 |
}
|
998 |
}
|
1053 |
}
|
1054 |
|
1055 |
if (!preg_match('//u', $string)) {
|
1056 |
+
throw new RuntimeError('The string to escape is not a valid UTF-8 string.');
|
1057 |
}
|
1058 |
|
1059 |
$string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', '_twig_escape_js_callback', $string);
|
1070 |
}
|
1071 |
|
1072 |
if (!preg_match('//u', $string)) {
|
1073 |
+
throw new RuntimeError('The string to escape is not a valid UTF-8 string.');
|
1074 |
}
|
1075 |
|
1076 |
$string = preg_replace_callback('#[^a-zA-Z0-9]#Su', '_twig_escape_css_callback', $string);
|
1087 |
}
|
1088 |
|
1089 |
if (!preg_match('//u', $string)) {
|
1090 |
+
throw new RuntimeError('The string to escape is not a valid UTF-8 string.');
|
1091 |
}
|
1092 |
|
1093 |
$string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', '_twig_escape_html_attr_callback', $string);
|
1105 |
static $escapers;
|
1106 |
|
1107 |
if (null === $escapers) {
|
1108 |
+
$escapers = $env->getExtension('\Twig\Extension\CoreExtension')->getEscapers();
|
1109 |
}
|
1110 |
|
1111 |
if (isset($escapers[$strategy])) {
|
1112 |
+
return \call_user_func($escapers[$strategy], $env, $string, $charset);
|
1113 |
}
|
1114 |
|
1115 |
$validStrategies = implode(', ', array_merge(['html', 'js', 'url', 'css', 'html_attr'], array_keys($escapers)));
|
1116 |
|
1117 |
+
throw new RuntimeError(sprintf('Invalid escaping strategy "%s" (valid ones: %s).', $strategy, $validStrategies));
|
1118 |
}
|
1119 |
}
|
1120 |
|
1124 |
function twig_escape_filter_is_safe(Twig_Node $filterArgs)
|
1125 |
{
|
1126 |
foreach ($filterArgs as $arg) {
|
1127 |
+
if ($arg instanceof ConstantExpression) {
|
1128 |
return [$arg->getAttribute('value')];
|
1129 |
}
|
1130 |
|
1134 |
return ['html'];
|
1135 |
}
|
1136 |
|
1137 |
+
if (\function_exists('mb_convert_encoding')) {
|
1138 |
function twig_convert_encoding($string, $to, $from)
|
1139 |
{
|
1140 |
return mb_convert_encoding($string, $to, $from);
|
1141 |
}
|
1142 |
+
} elseif (\function_exists('iconv')) {
|
1143 |
function twig_convert_encoding($string, $to, $from)
|
1144 |
{
|
1145 |
return iconv($from, $to, $string);
|
1147 |
} else {
|
1148 |
function twig_convert_encoding($string, $to, $from)
|
1149 |
{
|
1150 |
+
throw new RuntimeError('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).');
|
1151 |
}
|
1152 |
}
|
1153 |
|
1154 |
+
if (\function_exists('mb_ord')) {
|
1155 |
function twig_ord($string)
|
1156 |
{
|
1157 |
return mb_ord($string, 'UTF-8');
|
1201 |
$char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');
|
1202 |
$char = strtoupper(bin2hex($char));
|
1203 |
|
1204 |
+
if (4 >= \strlen($char)) {
|
1205 |
return sprintf('\u%04s', $char);
|
1206 |
}
|
1207 |
|
1212 |
{
|
1213 |
$char = $matches[0];
|
1214 |
|
1215 |
+
return sprintf('\\%X ', 1 === \strlen($char) ? \ord($char) : twig_ord($char));
|
1216 |
}
|
1217 |
|
1218 |
/**
|
1224 |
function _twig_escape_html_attr_callback($matches)
|
1225 |
{
|
1226 |
$chr = $matches[0];
|
1227 |
+
$ord = \ord($chr);
|
1228 |
|
1229 |
/*
|
1230 |
* The following replaces characters undefined in HTML with the
|
1238 |
* Check if the current character to escape has a name entity we should
|
1239 |
* replace it with while grabbing the hex value of the character.
|
1240 |
*/
|
1241 |
+
if (1 == \strlen($chr)) {
|
1242 |
/*
|
1243 |
* While HTML supports far more named entities, the lowest common denominator
|
1244 |
* has become HTML5's XML Serialisation which is restricted to the those named
|
1267 |
}
|
1268 |
|
1269 |
// add multibyte extensions if possible
|
1270 |
+
if (\function_exists('mb_get_info')) {
|
1271 |
/**
|
1272 |
* Returns the length of a variable.
|
1273 |
*
|
1274 |
+
* @param mixed $thing A variable
|
|
|
1275 |
*
|
1276 |
* @return int The length of the value
|
1277 |
*/
|
1278 |
+
function twig_length_filter(Environment $env, $thing)
|
1279 |
{
|
1280 |
if (null === $thing) {
|
1281 |
return 0;
|
1286 |
}
|
1287 |
|
1288 |
if ($thing instanceof \SimpleXMLElement) {
|
1289 |
+
return \count($thing);
|
1290 |
}
|
1291 |
|
1292 |
+
if (\is_object($thing) && method_exists($thing, '__toString') && !$thing instanceof \Countable) {
|
1293 |
return mb_strlen((string) $thing, $env->getCharset());
|
1294 |
}
|
1295 |
|
1296 |
+
if ($thing instanceof \Countable || \is_array($thing)) {
|
1297 |
+
return \count($thing);
|
1298 |
}
|
1299 |
|
1300 |
if ($thing instanceof \IteratorAggregate) {
|
1307 |
/**
|
1308 |
* Converts a string to uppercase.
|
1309 |
*
|
1310 |
+
* @param string $string A string
|
|
|
1311 |
*
|
1312 |
* @return string The uppercased string
|
1313 |
*/
|
1314 |
+
function twig_upper_filter(Environment $env, $string)
|
1315 |
{
|
1316 |
if (null !== $charset = $env->getCharset()) {
|
1317 |
return mb_strtoupper($string, $charset);
|
1323 |
/**
|
1324 |
* Converts a string to lowercase.
|
1325 |
*
|
1326 |
+
* @param string $string A string
|
|
|
1327 |
*
|
1328 |
* @return string The lowercased string
|
1329 |
*/
|
1330 |
+
function twig_lower_filter(Environment $env, $string)
|
1331 |
{
|
1332 |
if (null !== $charset = $env->getCharset()) {
|
1333 |
return mb_strtolower($string, $charset);
|
1339 |
/**
|
1340 |
* Returns a titlecased string.
|
1341 |
*
|
1342 |
+
* @param string $string A string
|
|
|
1343 |
*
|
1344 |
* @return string The titlecased string
|
1345 |
*/
|
1346 |
+
function twig_title_string_filter(Environment $env, $string)
|
1347 |
{
|
1348 |
if (null !== $charset = $env->getCharset()) {
|
1349 |
return mb_convert_case($string, MB_CASE_TITLE, $charset);
|
1355 |
/**
|
1356 |
* Returns a capitalized string.
|
1357 |
*
|
1358 |
+
* @param string $string A string
|
|
|
1359 |
*
|
1360 |
* @return string The capitalized string
|
1361 |
*/
|
1362 |
+
function twig_capitalize_string_filter(Environment $env, $string)
|
1363 |
{
|
1364 |
if (null !== $charset = $env->getCharset()) {
|
1365 |
return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset).mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset);
|
1373 |
/**
|
1374 |
* Returns the length of a variable.
|
1375 |
*
|
1376 |
+
* @param mixed $thing A variable
|
|
|
1377 |
*
|
1378 |
* @return int The length of the value
|
1379 |
*/
|
1380 |
+
function twig_length_filter(Environment $env, $thing)
|
1381 |
{
|
1382 |
if (null === $thing) {
|
1383 |
return 0;
|
1384 |
}
|
1385 |
|
1386 |
if (is_scalar($thing)) {
|
1387 |
+
return \strlen($thing);
|
1388 |
}
|
1389 |
|
1390 |
if ($thing instanceof \SimpleXMLElement) {
|
1391 |
+
return \count($thing);
|
1392 |
}
|
1393 |
|
1394 |
+
if (\is_object($thing) && method_exists($thing, '__toString') && !$thing instanceof \Countable) {
|
1395 |
+
return \strlen((string) $thing);
|
1396 |
}
|
1397 |
|
1398 |
+
if ($thing instanceof \Countable || \is_array($thing)) {
|
1399 |
+
return \count($thing);
|
1400 |
}
|
1401 |
|
1402 |
if ($thing instanceof \IteratorAggregate) {
|
1409 |
/**
|
1410 |
* Returns a titlecased string.
|
1411 |
*
|
1412 |
+
* @param string $string A string
|
|
|
1413 |
*
|
1414 |
* @return string The titlecased string
|
1415 |
*/
|
1416 |
+
function twig_title_string_filter(Environment $env, $string)
|
1417 |
{
|
1418 |
return ucwords(strtolower($string));
|
1419 |
}
|
1421 |
/**
|
1422 |
* Returns a capitalized string.
|
1423 |
*
|
1424 |
+
* @param string $string A string
|
|
|
1425 |
*
|
1426 |
* @return string The capitalized string
|
1427 |
*/
|
1428 |
+
function twig_capitalize_string_filter(Environment $env, $string)
|
1429 |
{
|
1430 |
return ucfirst(strtolower($string));
|
1431 |
}
|
1436 |
*/
|
1437 |
function twig_ensure_traversable($seq)
|
1438 |
{
|
1439 |
+
if ($seq instanceof \Traversable || \is_array($seq)) {
|
1440 |
return $seq;
|
1441 |
}
|
1442 |
|
1446 |
/**
|
1447 |
* Checks if a variable is empty.
|
1448 |
*
|
1449 |
+
* {# evaluates to true if the foo variable is null, false, or the empty string #}
|
1450 |
+
* {% if foo is empty %}
|
1451 |
+
* {# ... #}
|
1452 |
+
* {% endif %}
|
|
|
|
|
1453 |
*
|
1454 |
* @param mixed $value A variable
|
1455 |
*
|
1457 |
*/
|
1458 |
function twig_test_empty($value)
|
1459 |
{
|
1460 |
+
if ($value instanceof \Countable) {
|
1461 |
+
return 0 == \count($value);
|
1462 |
}
|
1463 |
|
1464 |
+
if (\is_object($value) && method_exists($value, '__toString')) {
|
1465 |
return '' === (string) $value;
|
1466 |
}
|
1467 |
|
1471 |
/**
|
1472 |
* Checks if a variable is traversable.
|
1473 |
*
|
1474 |
+
* {# evaluates to true if the foo variable is an array or a traversable object #}
|
1475 |
+
* {% if foo is iterable %}
|
1476 |
+
* {# ... #}
|
1477 |
+
* {% endif %}
|
|
|
|
|
1478 |
*
|
1479 |
* @param mixed $value A variable
|
1480 |
*
|
1482 |
*/
|
1483 |
function twig_test_iterable($value)
|
1484 |
{
|
1485 |
+
return $value instanceof \Traversable || \is_array($value);
|
1486 |
}
|
1487 |
|
1488 |
/**
|
1489 |
* Renders a template.
|
1490 |
*
|
1491 |
+
* @param array $context
|
1492 |
+
* @param string|array $template The template to render or an array of templates to try consecutively
|
1493 |
+
* @param array $variables The variables to pass to the template
|
1494 |
+
* @param bool $withContext
|
1495 |
+
* @param bool $ignoreMissing Whether to ignore missing templates or not
|
1496 |
+
* @param bool $sandboxed Whether to sandbox the template or not
|
|
|
1497 |
*
|
1498 |
* @return string The rendered template
|
1499 |
*/
|
1505 |
$variables = array_merge($context, $variables);
|
1506 |
}
|
1507 |
|
1508 |
+
if ($isSandboxed = $sandboxed && $env->hasExtension('\Twig\Extension\SandboxExtension')) {
|
1509 |
+
$sandbox = $env->getExtension('\Twig\Extension\SandboxExtension');
|
1510 |
if (!$alreadySandboxed = $sandbox->isSandboxed()) {
|
1511 |
$sandbox->enableSandbox();
|
1512 |
}
|
1515 |
$result = '';
|
1516 |
try {
|
1517 |
$result = $env->resolveTemplate($template)->render($variables);
|
1518 |
+
} catch (LoaderError $e) {
|
1519 |
if (!$ignoreMissing) {
|
1520 |
if ($isSandboxed && !$alreadySandboxed) {
|
1521 |
$sandbox->disableSandbox();
|
1523 |
|
1524 |
throw $e;
|
1525 |
}
|
1526 |
+
} catch (\Throwable $e) {
|
1527 |
if ($isSandboxed && !$alreadySandboxed) {
|
1528 |
$sandbox->disableSandbox();
|
1529 |
}
|
1530 |
|
1531 |
throw $e;
|
1532 |
+
} catch (\Exception $e) {
|
1533 |
if ($isSandboxed && !$alreadySandboxed) {
|
1534 |
$sandbox->disableSandbox();
|
1535 |
}
|
1547 |
/**
|
1548 |
* Returns a template content without rendering it.
|
1549 |
*
|
1550 |
+
* @param string $name The template name
|
1551 |
+
* @param bool $ignoreMissing Whether to ignore missing templates or not
|
|
|
1552 |
*
|
1553 |
* @return string The template source
|
1554 |
*/
|
1556 |
{
|
1557 |
$loader = $env->getLoader();
|
1558 |
try {
|
1559 |
+
if (!$loader instanceof SourceContextLoaderInterface) {
|
1560 |
return $loader->getSource($name);
|
1561 |
} else {
|
1562 |
return $loader->getSourceContext($name)->getCode();
|
1563 |
}
|
1564 |
+
} catch (LoaderError $e) {
|
1565 |
if (!$ignoreMissing) {
|
1566 |
throw $e;
|
1567 |
}
|
1579 |
function twig_constant($constant, $object = null)
|
1580 |
{
|
1581 |
if (null !== $object) {
|
1582 |
+
$constant = \get_class($object).'::'.$constant;
|
1583 |
}
|
1584 |
|
1585 |
+
return \constant($constant);
|
1586 |
}
|
1587 |
|
1588 |
/**
|
1596 |
function twig_constant_is_defined($constant, $object = null)
|
1597 |
{
|
1598 |
if (null !== $object) {
|
1599 |
+
$constant = \get_class($object).'::'.$constant;
|
1600 |
}
|
1601 |
|
1602 |
+
return \defined($constant);
|
1603 |
}
|
1604 |
|
1605 |
/**
|
1613 |
*/
|
1614 |
function twig_array_batch($items, $size, $fill = null)
|
1615 |
{
|
1616 |
+
if ($items instanceof \Traversable) {
|
1617 |
$items = iterator_to_array($items, false);
|
1618 |
}
|
1619 |
|
1622 |
$result = array_chunk($items, $size, true);
|
1623 |
|
1624 |
if (null !== $fill && !empty($result)) {
|
1625 |
+
$last = \count($result) - 1;
|
1626 |
+
if ($fillCount = $size - \count($result[$last])) {
|
1627 |
$result[$last] = array_merge(
|
1628 |
$result[$last],
|
1629 |
array_fill(0, $fillCount, $fill)
|
vendor/twig/twig/lib/Twig/Extension/Debug.php
CHANGED
@@ -9,15 +9,19 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* @final
|
14 |
*/
|
15 |
-
class Twig_Extension_Debug extends
|
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
|
@@ -27,7 +31,7 @@ class Twig_Extension_Debug extends Twig_Extension
|
|
27 |
;
|
28 |
|
29 |
return [
|
30 |
-
new
|
31 |
];
|
32 |
}
|
33 |
|
@@ -45,11 +49,11 @@ function twig_var_dump(Twig_Environment $env, $context)
|
|
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
|
53 |
$vars[$key] = $value;
|
54 |
}
|
55 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Extension\AbstractExtension;
|
13 |
+
use Twig\Template;
|
14 |
+
use Twig\TwigFunction;
|
15 |
+
|
16 |
/**
|
17 |
* @final
|
18 |
*/
|
19 |
+
class Twig_Extension_Debug extends AbstractExtension
|
20 |
{
|
21 |
public function getFunctions()
|
22 |
{
|
23 |
// dump is safe if var_dump is overridden by xdebug
|
24 |
+
$isDumpOutputHtmlSafe = \extension_loaded('xdebug')
|
25 |
// false means that it was not set (and the default is on) or it explicitly enabled
|
26 |
&& (false === ini_get('xdebug.overload_var_dump') || ini_get('xdebug.overload_var_dump'))
|
27 |
// false means that it was not set (and the default is on) or it explicitly enabled
|
31 |
;
|
32 |
|
33 |
return [
|
34 |
+
new TwigFunction('dump', 'twig_var_dump', ['is_safe' => $isDumpOutputHtmlSafe ? ['html'] : [], 'needs_context' => true, 'needs_environment' => true]),
|
35 |
];
|
36 |
}
|
37 |
|
49 |
|
50 |
ob_start();
|
51 |
|
52 |
+
$count = \func_num_args();
|
53 |
if (2 === $count) {
|
54 |
$vars = [];
|
55 |
foreach ($context as $key => $value) {
|
56 |
+
if (!$value instanceof Template) {
|
57 |
$vars[$key] = $value;
|
58 |
}
|
59 |
}
|
vendor/twig/twig/lib/Twig/Extension/Escaper.php
CHANGED
@@ -9,10 +9,15 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* @final
|
14 |
*/
|
15 |
-
class Twig_Extension_Escaper extends
|
16 |
{
|
17 |
protected $defaultStrategy;
|
18 |
|
@@ -28,18 +33,18 @@ class Twig_Extension_Escaper extends Twig_Extension
|
|
28 |
|
29 |
public function getTokenParsers()
|
30 |
{
|
31 |
-
return [new
|
32 |
}
|
33 |
|
34 |
public function getNodeVisitors()
|
35 |
{
|
36 |
-
return [new
|
37 |
}
|
38 |
|
39 |
public function getFilters()
|
40 |
{
|
41 |
return [
|
42 |
-
new
|
43 |
];
|
44 |
}
|
45 |
|
@@ -67,7 +72,7 @@ class Twig_Extension_Escaper extends Twig_Extension
|
|
67 |
}
|
68 |
|
69 |
if ('name' === $defaultStrategy) {
|
70 |
-
$defaultStrategy = ['
|
71 |
}
|
72 |
|
73 |
$this->defaultStrategy = $defaultStrategy;
|
@@ -84,8 +89,8 @@ class Twig_Extension_Escaper extends Twig_Extension
|
|
84 |
{
|
85 |
// disable string callables to avoid calling a function named html or js,
|
86 |
// or any other upcoming escaping strategy
|
87 |
-
if (
|
88 |
-
return call_user_func($this->defaultStrategy, $name);
|
89 |
}
|
90 |
|
91 |
return $this->defaultStrategy;
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Extension\AbstractExtension;
|
13 |
+
use Twig\NodeVisitor\EscaperNodeVisitor;
|
14 |
+
use Twig\TokenParser\AutoEscapeTokenParser;
|
15 |
+
use Twig\TwigFilter;
|
16 |
+
|
17 |
/**
|
18 |
* @final
|
19 |
*/
|
20 |
+
class Twig_Extension_Escaper extends AbstractExtension
|
21 |
{
|
22 |
protected $defaultStrategy;
|
23 |
|
33 |
|
34 |
public function getTokenParsers()
|
35 |
{
|
36 |
+
return [new AutoEscapeTokenParser()];
|
37 |
}
|
38 |
|
39 |
public function getNodeVisitors()
|
40 |
{
|
41 |
+
return [new EscaperNodeVisitor()];
|
42 |
}
|
43 |
|
44 |
public function getFilters()
|
45 |
{
|
46 |
return [
|
47 |
+
new TwigFilter('raw', 'twig_raw_filter', ['is_safe' => ['all']]),
|
48 |
];
|
49 |
}
|
50 |
|
72 |
}
|
73 |
|
74 |
if ('name' === $defaultStrategy) {
|
75 |
+
$defaultStrategy = ['\Twig\FileExtensionEscapingStrategy', 'guess'];
|
76 |
}
|
77 |
|
78 |
$this->defaultStrategy = $defaultStrategy;
|
89 |
{
|
90 |
// disable string callables to avoid calling a function named html or js,
|
91 |
// or any other upcoming escaping strategy
|
92 |
+
if (!\is_string($this->defaultStrategy) && false !== $this->defaultStrategy) {
|
93 |
+
return \call_user_func($this->defaultStrategy, $name);
|
94 |
}
|
95 |
|
96 |
return $this->defaultStrategy;
|
vendor/twig/twig/lib/Twig/Extension/GlobalsInterface.php
CHANGED
@@ -10,7 +10,7 @@
|
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
-
* Enables usage of the deprecated
|
14 |
*
|
15 |
* Explicitly implement this interface if you really need to implement the
|
16 |
* deprecated getGlobals() method in your extensions.
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
+
* Enables usage of the deprecated Twig\Extension\AbstractExtension::getGlobals() method.
|
14 |
*
|
15 |
* Explicitly implement this interface if you really need to implement the
|
16 |
* deprecated getGlobals() method in your extensions.
|
vendor/twig/twig/lib/Twig/Extension/InitRuntimeInterface.php
CHANGED
@@ -10,7 +10,7 @@
|
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
-
* Enables usage of the deprecated
|
14 |
*
|
15 |
* Explicitly implement this interface if you really need to implement the
|
16 |
* deprecated initRuntime() method in your extensions.
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
+
* Enables usage of the deprecated Twig\Extension\AbstractExtension::initRuntime() method.
|
14 |
*
|
15 |
* Explicitly implement this interface if you really need to implement the
|
16 |
* deprecated initRuntime() method in your extensions.
|
vendor/twig/twig/lib/Twig/Extension/Optimizer.php
CHANGED
@@ -9,10 +9,13 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
12 |
/**
|
13 |
* @final
|
14 |
*/
|
15 |
-
class Twig_Extension_Optimizer extends
|
16 |
{
|
17 |
protected $optimizers;
|
18 |
|
@@ -23,7 +26,7 @@ class Twig_Extension_Optimizer extends Twig_Extension
|
|
23 |
|
24 |
public function getNodeVisitors()
|
25 |
{
|
26 |
-
return [new
|
27 |
}
|
28 |
|
29 |
public function getName()
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Extension\AbstractExtension;
|
13 |
+
use Twig\NodeVisitor\OptimizerNodeVisitor;
|
14 |
+
|
15 |
/**
|
16 |
* @final
|
17 |
*/
|
18 |
+
class Twig_Extension_Optimizer extends AbstractExtension
|
19 |
{
|
20 |
protected $optimizers;
|
21 |
|
26 |
|
27 |
public function getNodeVisitors()
|
28 |
{
|
29 |
+
return [new OptimizerNodeVisitor($this->optimizers)];
|
30 |
}
|
31 |
|
32 |
public function getName()
|
vendor/twig/twig/lib/Twig/Extension/Profiler.php
CHANGED
@@ -9,34 +9,38 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
-
|
|
|
|
|
|
|
|
|
13 |
{
|
14 |
private $actives = [];
|
15 |
|
16 |
-
public function __construct(
|
17 |
{
|
18 |
$this->actives[] = $profile;
|
19 |
}
|
20 |
|
21 |
-
public function enter(
|
22 |
{
|
23 |
$this->actives[0]->addProfile($profile);
|
24 |
array_unshift($this->actives, $profile);
|
25 |
}
|
26 |
|
27 |
-
public function leave(
|
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
|
40 |
}
|
41 |
|
42 |
public function getName()
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Extension\AbstractExtension;
|
13 |
+
use Twig\Profiler\NodeVisitor\ProfilerNodeVisitor;
|
14 |
+
use Twig\Profiler\Profile;
|
15 |
+
|
16 |
+
class Twig_Extension_Profiler extends AbstractExtension
|
17 |
{
|
18 |
private $actives = [];
|
19 |
|
20 |
+
public function __construct(Profile $profile)
|
21 |
{
|
22 |
$this->actives[] = $profile;
|
23 |
}
|
24 |
|
25 |
+
public function enter(Profile $profile)
|
26 |
{
|
27 |
$this->actives[0]->addProfile($profile);
|
28 |
array_unshift($this->actives, $profile);
|
29 |
}
|
30 |
|
31 |
+
public function leave(Profile $profile)
|
32 |
{
|
33 |
$profile->leave();
|
34 |
array_shift($this->actives);
|
35 |
|
36 |
+
if (1 === \count($this->actives)) {
|
37 |
$this->actives[0]->leave();
|
38 |
}
|
39 |
}
|
40 |
|
41 |
public function getNodeVisitors()
|
42 |
{
|
43 |
+
return [new ProfilerNodeVisitor(\get_class($this))];
|
44 |
}
|
45 |
|
46 |
public function getName()
|
vendor/twig/twig/lib/Twig/Extension/Sandbox.php
CHANGED
@@ -9,16 +9,21 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* @final
|
14 |
*/
|
15 |
-
class Twig_Extension_Sandbox extends
|
16 |
{
|
17 |
protected $sandboxedGlobally;
|
18 |
protected $sandboxed;
|
19 |
protected $policy;
|
20 |
|
21 |
-
public function __construct(
|
22 |
{
|
23 |
$this->policy = $policy;
|
24 |
$this->sandboxedGlobally = $sandboxed;
|
@@ -26,12 +31,12 @@ class Twig_Extension_Sandbox extends Twig_Extension
|
|
26 |
|
27 |
public function getTokenParsers()
|
28 |
{
|
29 |
-
return [new
|
30 |
}
|
31 |
|
32 |
public function getNodeVisitors()
|
33 |
{
|
34 |
-
return [new
|
35 |
}
|
36 |
|
37 |
public function enableSandbox()
|
@@ -54,7 +59,7 @@ class Twig_Extension_Sandbox extends Twig_Extension
|
|
54 |
return $this->sandboxedGlobally;
|
55 |
}
|
56 |
|
57 |
-
public function setSecurityPolicy(
|
58 |
{
|
59 |
$this->policy = $policy;
|
60 |
}
|
@@ -87,7 +92,7 @@ class Twig_Extension_Sandbox extends Twig_Extension
|
|
87 |
|
88 |
public function ensureToStringAllowed($obj)
|
89 |
{
|
90 |
-
if ($this->isSandboxed() && is_object($obj)) {
|
91 |
$this->policy->checkMethodAllowed($obj, '__toString');
|
92 |
}
|
93 |
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Extension\AbstractExtension;
|
13 |
+
use Twig\NodeVisitor\SandboxNodeVisitor;
|
14 |
+
use Twig\Sandbox\SecurityPolicyInterface;
|
15 |
+
use Twig\TokenParser\SandboxTokenParser;
|
16 |
+
|
17 |
/**
|
18 |
* @final
|
19 |
*/
|
20 |
+
class Twig_Extension_Sandbox extends AbstractExtension
|
21 |
{
|
22 |
protected $sandboxedGlobally;
|
23 |
protected $sandboxed;
|
24 |
protected $policy;
|
25 |
|
26 |
+
public function __construct(SecurityPolicyInterface $policy, $sandboxed = false)
|
27 |
{
|
28 |
$this->policy = $policy;
|
29 |
$this->sandboxedGlobally = $sandboxed;
|
31 |
|
32 |
public function getTokenParsers()
|
33 |
{
|
34 |
+
return [new SandboxTokenParser()];
|
35 |
}
|
36 |
|
37 |
public function getNodeVisitors()
|
38 |
{
|
39 |
+
return [new SandboxNodeVisitor()];
|
40 |
}
|
41 |
|
42 |
public function enableSandbox()
|
59 |
return $this->sandboxedGlobally;
|
60 |
}
|
61 |
|
62 |
+
public function setSecurityPolicy(SecurityPolicyInterface $policy)
|
63 |
{
|
64 |
$this->policy = $policy;
|
65 |
}
|
92 |
|
93 |
public function ensureToStringAllowed($obj)
|
94 |
{
|
95 |
+
if ($this->isSandboxed() && \is_object($obj)) {
|
96 |
$this->policy->checkMethodAllowed($obj, '__toString');
|
97 |
}
|
98 |
|
vendor/twig/twig/lib/Twig/Extension/Staging.php
CHANGED
@@ -9,6 +9,10 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Internal class.
|
14 |
*
|
@@ -18,7 +22,7 @@
|
|
18 |
*
|
19 |
* @internal
|
20 |
*/
|
21 |
-
class Twig_Extension_Staging extends
|
22 |
{
|
23 |
protected $functions = [];
|
24 |
protected $filters = [];
|
@@ -55,7 +59,7 @@ class Twig_Extension_Staging extends Twig_Extension
|
|
55 |
return $this->filters;
|
56 |
}
|
57 |
|
58 |
-
public function addNodeVisitor(
|
59 |
{
|
60 |
$this->visitors[] = $visitor;
|
61 |
}
|
@@ -65,7 +69,7 @@ class Twig_Extension_Staging extends Twig_Extension
|
|
65 |
return $this->visitors;
|
66 |
}
|
67 |
|
68 |
-
public function addTokenParser(
|
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);
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Extension\AbstractExtension;
|
13 |
+
use Twig\NodeVisitor\NodeVisitorInterface;
|
14 |
+
use Twig\TokenParser\TokenParserInterface;
|
15 |
+
|
16 |
/**
|
17 |
* Internal class.
|
18 |
*
|
22 |
*
|
23 |
* @internal
|
24 |
*/
|
25 |
+
class Twig_Extension_Staging extends AbstractExtension
|
26 |
{
|
27 |
protected $functions = [];
|
28 |
protected $filters = [];
|
59 |
return $this->filters;
|
60 |
}
|
61 |
|
62 |
+
public function addNodeVisitor(NodeVisitorInterface $visitor)
|
63 |
{
|
64 |
$this->visitors[] = $visitor;
|
65 |
}
|
69 |
return $this->visitors;
|
70 |
}
|
71 |
|
72 |
+
public function addTokenParser(TokenParserInterface $parser)
|
73 |
{
|
74 |
if (isset($this->tokenParsers[$parser->getTag()])) {
|
75 |
@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);
|
vendor/twig/twig/lib/Twig/Extension/StringLoader.php
CHANGED
@@ -9,15 +9,19 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* @final
|
14 |
*/
|
15 |
-
class Twig_Extension_StringLoader extends
|
16 |
{
|
17 |
public function getFunctions()
|
18 |
{
|
19 |
return [
|
20 |
-
new
|
21 |
];
|
22 |
}
|
23 |
|
@@ -30,14 +34,11 @@ class Twig_Extension_StringLoader extends Twig_Extension
|
|
30 |
/**
|
31 |
* Loads a template from a string.
|
32 |
*
|
33 |
-
*
|
34 |
-
* {{ include(template_from_string("Hello {{ name }}")) }}
|
35 |
-
* </pre>
|
36 |
*
|
37 |
-
* @param
|
38 |
-
* @param string $template A template as a string or object implementing __toString()
|
39 |
*
|
40 |
-
* @return
|
41 |
*/
|
42 |
function twig_template_from_string(Twig_Environment $env, $template)
|
43 |
{
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Extension\AbstractExtension;
|
13 |
+
use Twig\Template;
|
14 |
+
use Twig\TwigFunction;
|
15 |
+
|
16 |
/**
|
17 |
* @final
|
18 |
*/
|
19 |
+
class Twig_Extension_StringLoader extends AbstractExtension
|
20 |
{
|
21 |
public function getFunctions()
|
22 |
{
|
23 |
return [
|
24 |
+
new TwigFunction('template_from_string', 'twig_template_from_string', ['needs_environment' => true]),
|
25 |
];
|
26 |
}
|
27 |
|
34 |
/**
|
35 |
* Loads a template from a string.
|
36 |
*
|
37 |
+
* {{ include(template_from_string("Hello {{ name }}")) }}
|
|
|
|
|
38 |
*
|
39 |
+
* @param string $template A template as a string or object implementing __toString()
|
|
|
40 |
*
|
41 |
+
* @return Template
|
42 |
*/
|
43 |
function twig_template_from_string(Twig_Environment $env, $template)
|
44 |
{
|
vendor/twig/twig/lib/Twig/ExtensionInterface.php
CHANGED
@@ -9,6 +9,13 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Interface implemented by extension classes.
|
14 |
*
|
@@ -23,40 +30,40 @@ interface Twig_ExtensionInterface
|
|
23 |
*
|
24 |
* @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead
|
25 |
*/
|
26 |
-
public function initRuntime(
|
27 |
|
28 |
/**
|
29 |
* Returns the token parser instances to add to the existing list.
|
30 |
*
|
31 |
-
* @return
|
32 |
*/
|
33 |
public function getTokenParsers();
|
34 |
|
35 |
/**
|
36 |
* Returns the node visitor instances to add to the existing list.
|
37 |
*
|
38 |
-
* @return
|
39 |
*/
|
40 |
public function getNodeVisitors();
|
41 |
|
42 |
/**
|
43 |
* Returns a list of filters to add to the existing list.
|
44 |
*
|
45 |
-
* @return
|
46 |
*/
|
47 |
public function getFilters();
|
48 |
|
49 |
/**
|
50 |
* Returns a list of tests to add to the existing list.
|
51 |
*
|
52 |
-
* @return
|
53 |
*/
|
54 |
public function getTests();
|
55 |
|
56 |
/**
|
57 |
* Returns a list of functions to add to the existing list.
|
58 |
*
|
59 |
-
* @return
|
60 |
*/
|
61 |
public function getFunctions();
|
62 |
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Environment;
|
13 |
+
use Twig\NodeVisitor\NodeVisitorInterface;
|
14 |
+
use Twig\TokenParser\TokenParserInterface;
|
15 |
+
use Twig\TwigFilter;
|
16 |
+
use Twig\TwigFunction;
|
17 |
+
use Twig\TwigTest;
|
18 |
+
|
19 |
/**
|
20 |
* Interface implemented by extension classes.
|
21 |
*
|
30 |
*
|
31 |
* @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead
|
32 |
*/
|
33 |
+
public function initRuntime(Environment $environment);
|
34 |
|
35 |
/**
|
36 |
* Returns the token parser instances to add to the existing list.
|
37 |
*
|
38 |
+
* @return TokenParserInterface[]
|
39 |
*/
|
40 |
public function getTokenParsers();
|
41 |
|
42 |
/**
|
43 |
* Returns the node visitor instances to add to the existing list.
|
44 |
*
|
45 |
+
* @return NodeVisitorInterface[]
|
46 |
*/
|
47 |
public function getNodeVisitors();
|
48 |
|
49 |
/**
|
50 |
* Returns a list of filters to add to the existing list.
|
51 |
*
|
52 |
+
* @return TwigFilter[]
|
53 |
*/
|
54 |
public function getFilters();
|
55 |
|
56 |
/**
|
57 |
* Returns a list of tests to add to the existing list.
|
58 |
*
|
59 |
+
* @return TwigTest[]
|
60 |
*/
|
61 |
public function getTests();
|
62 |
|
63 |
/**
|
64 |
* Returns a list of functions to add to the existing list.
|
65 |
*
|
66 |
+
* @return TwigFunction[]
|
67 |
*/
|
68 |
public function getFunctions();
|
69 |
|
vendor/twig/twig/lib/Twig/FactoryRuntimeLoader.php
CHANGED
@@ -9,12 +9,14 @@
|
|
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
|
18 |
{
|
19 |
private $map;
|
20 |
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\RuntimeLoader\RuntimeLoaderInterface;
|
13 |
+
|
14 |
/**
|
15 |
* Lazy loads the runtime implementations for a Twig element.
|
16 |
*
|
17 |
* @author Robin Chalas <robin.chalas@gmail.com>
|
18 |
*/
|
19 |
+
class Twig_FactoryRuntimeLoader implements RuntimeLoaderInterface
|
20 |
{
|
21 |
private $map;
|
22 |
|
vendor/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php
CHANGED
@@ -31,7 +31,7 @@ class Twig_FileExtensionEscapingStrategy
|
|
31 |
*/
|
32 |
public static function guess($name)
|
33 |
{
|
34 |
-
if (in_array(substr($name, -1), ['/', '\\'])) {
|
35 |
return 'html'; // return html for directories
|
36 |
}
|
37 |
|
31 |
*/
|
32 |
public static function guess($name)
|
33 |
{
|
34 |
+
if (\in_array(substr($name, -1), ['/', '\\'])) {
|
35 |
return 'html'; // return html for directories
|
36 |
}
|
37 |
|
vendor/twig/twig/lib/Twig/Filter.php
CHANGED
@@ -9,6 +9,8 @@
|
|
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 |
/**
|
@@ -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(
|
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_SimpleFilter instead.', E_USER_DEPRECATED);
|
15 |
|
16 |
/**
|
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 |
|
vendor/twig/twig/lib/Twig/Filter/Method.php
CHANGED
@@ -9,6 +9,8 @@
|
|
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 |
/**
|
@@ -25,7 +27,7 @@ class Twig_Filter_Method extends Twig_Filter
|
|
25 |
protected $extension;
|
26 |
protected $method;
|
27 |
|
28 |
-
public function __construct(
|
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_SimpleFilter instead.', E_USER_DEPRECATED);
|
15 |
|
16 |
/**
|
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 |
}
|
vendor/twig/twig/lib/Twig/FilterInterface.php
CHANGED
@@ -9,6 +9,8 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
12 |
/**
|
13 |
* Represents a template filter.
|
14 |
*
|
@@ -31,7 +33,7 @@ interface Twig_FilterInterface
|
|
31 |
|
32 |
public function needsContext();
|
33 |
|
34 |
-
public function getSafe(
|
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 |
*
|
33 |
|
34 |
public function needsContext();
|
35 |
|
36 |
+
public function getSafe(Node $filterArgs);
|
37 |
|
38 |
public function getPreservesSafety();
|
39 |
|
vendor/twig/twig/lib/Twig/Function.php
CHANGED
@@ -9,6 +9,8 @@
|
|
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 |
/**
|
@@ -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(
|
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_SimpleFunction instead.', E_USER_DEPRECATED);
|
15 |
|
16 |
/**
|
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 [];
|
vendor/twig/twig/lib/Twig/Function/Method.php
CHANGED
@@ -10,6 +10,8 @@
|
|
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 |
/**
|
@@ -26,7 +28,7 @@ class Twig_Function_Method extends Twig_Function
|
|
26 |
protected $extension;
|
27 |
protected $method;
|
28 |
|
29 |
-
public function __construct(
|
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_SimpleFunction instead.', E_USER_DEPRECATED);
|
16 |
|
17 |
/**
|
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 |
}
|
vendor/twig/twig/lib/Twig/FunctionInterface.php
CHANGED
@@ -10,6 +10,8 @@
|
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
|
|
|
|
13 |
/**
|
14 |
* Represents a template function.
|
15 |
*
|
@@ -32,7 +34,7 @@ interface Twig_FunctionInterface
|
|
32 |
|
33 |
public function needsContext();
|
34 |
|
35 |
-
public function getSafe(
|
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 |
*
|
34 |
|
35 |
public function needsContext();
|
36 |
|
37 |
+
public function getSafe(Node $filterArgs);
|
38 |
|
39 |
public function setArguments($arguments);
|
40 |
|
vendor/twig/twig/lib/Twig/Lexer.php
CHANGED
@@ -10,6 +10,12 @@
|
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
/**
|
14 |
* Lexes a template string.
|
15 |
*
|
@@ -49,7 +55,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
49 |
const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As';
|
50 |
const PUNCTUATION = '()[]{}?:.,|';
|
51 |
|
52 |
-
public function __construct(
|
53 |
{
|
54 |
$this->env = $env;
|
55 |
|
@@ -77,9 +83,9 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
77 |
|
78 |
public function tokenize($code, $name = null)
|
79 |
{
|
80 |
-
if (!$code instanceof
|
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
|
83 |
} else {
|
84 |
$this->source = $code;
|
85 |
}
|
@@ -88,7 +94,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
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 {
|
@@ -99,7 +105,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
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 = [];
|
@@ -136,25 +142,25 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
136 |
}
|
137 |
}
|
138 |
|
139 |
-
$this->pushToken(
|
140 |
|
141 |
if (!empty($this->brackets)) {
|
142 |
list($expect, $lineno) = array_pop($this->brackets);
|
143 |
-
throw new
|
144 |
}
|
145 |
|
146 |
if ($mbEncoding) {
|
147 |
mb_internal_encoding($mbEncoding);
|
148 |
}
|
149 |
|
150 |
-
return new
|
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(
|
158 |
$this->cursor = $this->end;
|
159 |
|
160 |
return;
|
@@ -163,7 +169,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
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];
|
@@ -174,7 +180,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
174 |
if (isset($this->positions[2][$this->position][0])) {
|
175 |
$text = rtrim($text);
|
176 |
}
|
177 |
-
$this->pushToken(
|
178 |
$this->moveCursor($textContent.$position[0]);
|
179 |
|
180 |
switch ($this->positions[1][$this->position][0]) {
|
@@ -192,14 +198,14 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
192 |
$this->moveCursor($match[0]);
|
193 |
$this->lineno = (int) $match[1];
|
194 |
} else {
|
195 |
-
$this->pushToken(
|
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(
|
203 |
$this->pushState(self::STATE_VAR);
|
204 |
$this->currentVarBlockLine = $this->lineno;
|
205 |
break;
|
@@ -209,7 +215,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
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(
|
213 |
$this->moveCursor($match[0]);
|
214 |
$this->popState();
|
215 |
} else {
|
@@ -220,7 +226,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
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(
|
224 |
$this->moveCursor($match[0]);
|
225 |
$this->popState();
|
226 |
} else {
|
@@ -235,18 +241,18 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
235 |
$this->moveCursor($match[0]);
|
236 |
|
237 |
if ($this->cursor >= $this->end) {
|
238 |
-
throw new
|
239 |
}
|
240 |
}
|
241 |
|
242 |
// operators
|
243 |
if (preg_match($this->regexes['operator'], $this->code, $match, null, $this->cursor)) {
|
244 |
-
$this->pushToken(
|
245 |
$this->moveCursor($match[0]);
|
246 |
}
|
247 |
// names
|
248 |
elseif (preg_match(self::REGEX_NAME, $this->code, $match, null, $this->cursor)) {
|
249 |
-
$this->pushToken(
|
250 |
$this->moveCursor($match[0]);
|
251 |
}
|
252 |
// numbers
|
@@ -255,7 +261,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
255 |
if (ctype_digit($match[0]) && $number <= PHP_INT_MAX) {
|
256 |
$number = (int) $match[0]; // integers lower than the maximum
|
257 |
}
|
258 |
-
$this->pushToken(
|
259 |
$this->moveCursor($match[0]);
|
260 |
}
|
261 |
// punctuation
|
@@ -267,21 +273,21 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
267 |
// closing bracket
|
268 |
elseif (false !== strpos(')]}', $this->code[$this->cursor])) {
|
269 |
if (empty($this->brackets)) {
|
270 |
-
throw new
|
271 |
}
|
272 |
|
273 |
list($expect, $lineno) = array_pop($this->brackets);
|
274 |
if ($this->code[$this->cursor] != strtr($expect, '([{', ')]}')) {
|
275 |
-
throw new
|
276 |
}
|
277 |
}
|
278 |
|
279 |
-
$this->pushToken(
|
280 |
++$this->cursor;
|
281 |
}
|
282 |
// strings
|
283 |
elseif (preg_match(self::REGEX_STRING, $this->code, $match, null, $this->cursor)) {
|
284 |
-
$this->pushToken(
|
285 |
$this->moveCursor($match[0]);
|
286 |
}
|
287 |
// opening double quoted string
|
@@ -292,7 +298,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
292 |
}
|
293 |
// unlexable
|
294 |
else {
|
295 |
-
throw new
|
296 |
}
|
297 |
}
|
298 |
|
@@ -303,7 +309,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
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
|
307 |
}
|
308 |
|
309 |
$text = substr($this->code, $this->cursor, $match[0][1] - $this->cursor);
|
@@ -313,13 +319,13 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
313 |
$text = rtrim($text);
|
314 |
}
|
315 |
|
316 |
-
$this->pushToken(
|
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
|
323 |
}
|
324 |
|
325 |
$this->moveCursor(substr($this->code, $this->cursor, $match[0][1] - $this->cursor).$match[0][0]);
|
@@ -329,23 +335,23 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
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(
|
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(
|
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
|
342 |
}
|
343 |
|
344 |
$this->popState();
|
345 |
++$this->cursor;
|
346 |
} else {
|
347 |
// unlexable
|
348 |
-
throw new
|
349 |
}
|
350 |
}
|
351 |
|
@@ -354,7 +360,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
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(
|
358 |
$this->moveCursor($match[0]);
|
359 |
$this->popState();
|
360 |
} else {
|
@@ -365,16 +371,16 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
365 |
protected function pushToken($type, $value = '')
|
366 |
{
|
367 |
// do not push empty text tokens
|
368 |
-
if (
|
369 |
return;
|
370 |
}
|
371 |
|
372 |
-
$this->tokens[] = new
|
373 |
}
|
374 |
|
375 |
protected function moveCursor($text)
|
376 |
{
|
377 |
-
$this->cursor += strlen($text);
|
378 |
$this->lineno += substr_count($text, "\n");
|
379 |
}
|
380 |
|
@@ -416,8 +422,8 @@ class Twig_Lexer implements Twig_LexerInterface
|
|
416 |
|
417 |
protected function popState()
|
418 |
{
|
419 |
-
if (0 === count($this->states)) {
|
420 |
-
throw new
|
421 |
}
|
422 |
|
423 |
$this->state = array_pop($this->states);
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Environment;
|
14 |
+
use Twig\Error\SyntaxError;
|
15 |
+
use Twig\Source;
|
16 |
+
use Twig\Token;
|
17 |
+
use Twig\TokenStream;
|
18 |
+
|
19 |
/**
|
20 |
* Lexes a template string.
|
21 |
*
|
55 |
const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As';
|
56 |
const PUNCTUATION = '()[]{}?:.,|';
|
57 |
|
58 |
+
public function __construct(Environment $env, array $options = [])
|
59 |
{
|
60 |
$this->env = $env;
|
61 |
|
83 |
|
84 |
public function tokenize($code, $name = null)
|
85 |
{
|
86 |
+
if (!$code instanceof Source) {
|
87 |
@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);
|
88 |
+
$this->source = new Source($code, $name);
|
89 |
} else {
|
90 |
$this->source = $code;
|
91 |
}
|
94 |
@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);
|
95 |
}
|
96 |
|
97 |
+
if (\function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
|
98 |
$mbEncoding = mb_internal_encoding();
|
99 |
mb_internal_encoding('ASCII');
|
100 |
} else {
|
105 |
$this->filename = $this->source->getName();
|
106 |
$this->cursor = 0;
|
107 |
$this->lineno = 1;
|
108 |
+
$this->end = \strlen($this->code);
|
109 |
$this->tokens = [];
|
110 |
$this->state = self::STATE_DATA;
|
111 |
$this->states = [];
|
142 |
}
|
143 |
}
|
144 |
|
145 |
+
$this->pushToken(Token::EOF_TYPE);
|
146 |
|
147 |
if (!empty($this->brackets)) {
|
148 |
list($expect, $lineno) = array_pop($this->brackets);
|
149 |
+
throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $lineno, $this->source);
|
150 |
}
|
151 |
|
152 |
if ($mbEncoding) {
|
153 |
mb_internal_encoding($mbEncoding);
|
154 |
}
|
155 |
|
156 |
+
return new TokenStream($this->tokens, $this->source);
|
157 |
}
|
158 |
|
159 |
protected function lexData()
|
160 |
{
|
161 |
// if no matches are left we return the rest of the template as simple text token
|
162 |
+
if ($this->position == \count($this->positions[0]) - 1) {
|
163 |
+
$this->pushToken(Token::TEXT_TYPE, substr($this->code, $this->cursor));
|
164 |
$this->cursor = $this->end;
|
165 |
|
166 |
return;
|
169 |
// Find the first token after the current cursor
|
170 |
$position = $this->positions[0][++$this->position];
|
171 |
while ($position[1] < $this->cursor) {
|
172 |
+
if ($this->position == \count($this->positions[0]) - 1) {
|
173 |
return;
|
174 |
}
|
175 |
$position = $this->positions[0][++$this->position];
|
180 |
if (isset($this->positions[2][$this->position][0])) {
|
181 |
$text = rtrim($text);
|
182 |
}
|
183 |
+
$this->pushToken(Token::TEXT_TYPE, $text);
|
184 |
$this->moveCursor($textContent.$position[0]);
|
185 |
|
186 |
switch ($this->positions[1][$this->position][0]) {
|
198 |
$this->moveCursor($match[0]);
|
199 |
$this->lineno = (int) $match[1];
|
200 |
} else {
|
201 |
+
$this->pushToken(Token::BLOCK_START_TYPE);
|
202 |
$this->pushState(self::STATE_BLOCK);
|
203 |
$this->currentVarBlockLine = $this->lineno;
|
204 |
}
|
205 |
break;
|
206 |
|
207 |
case $this->options['tag_variable'][0]:
|
208 |
+
$this->pushToken(Token::VAR_START_TYPE);
|
209 |
$this->pushState(self::STATE_VAR);
|
210 |
$this->currentVarBlockLine = $this->lineno;
|
211 |
break;
|
215 |
protected function lexBlock()
|
216 |
{
|
217 |
if (empty($this->brackets) && preg_match($this->regexes['lex_block'], $this->code, $match, null, $this->cursor)) {
|
218 |
+
$this->pushToken(Token::BLOCK_END_TYPE);
|
219 |
$this->moveCursor($match[0]);
|
220 |
$this->popState();
|
221 |
} else {
|
226 |
protected function lexVar()
|
227 |
{
|
228 |
if (empty($this->brackets) && preg_match($this->regexes['lex_var'], $this->code, $match, null, $this->cursor)) {
|
229 |
+
$this->pushToken(Token::VAR_END_TYPE);
|
230 |
$this->moveCursor($match[0]);
|
231 |
$this->popState();
|
232 |
} else {
|
241 |
$this->moveCursor($match[0]);
|
242 |
|
243 |
if ($this->cursor >= $this->end) {
|
244 |
+
throw new SyntaxError(sprintf('Unclosed "%s".', self::STATE_BLOCK === $this->state ? 'block' : 'variable'), $this->currentVarBlockLine, $this->source);
|
245 |
}
|
246 |
}
|
247 |
|
248 |
// operators
|
249 |
if (preg_match($this->regexes['operator'], $this->code, $match, null, $this->cursor)) {
|
250 |
+
$this->pushToken(Token::OPERATOR_TYPE, preg_replace('/\s+/', ' ', $match[0]));
|
251 |
$this->moveCursor($match[0]);
|
252 |
}
|
253 |
// names
|
254 |
elseif (preg_match(self::REGEX_NAME, $this->code, $match, null, $this->cursor)) {
|
255 |
+
$this->pushToken(Token::NAME_TYPE, $match[0]);
|
256 |
$this->moveCursor($match[0]);
|
257 |
}
|
258 |
// numbers
|
261 |
if (ctype_digit($match[0]) && $number <= PHP_INT_MAX) {
|
262 |
$number = (int) $match[0]; // integers lower than the maximum
|
263 |
}
|
264 |
+
$this->pushToken(Token::NUMBER_TYPE, $number);
|
265 |
$this->moveCursor($match[0]);
|
266 |
}
|
267 |
// punctuation
|
273 |
// closing bracket
|
274 |
elseif (false !== strpos(')]}', $this->code[$this->cursor])) {
|
275 |
if (empty($this->brackets)) {
|
276 |
+
throw new SyntaxError(sprintf('Unexpected "%s".', $this->code[$this->cursor]), $this->lineno, $this->source);
|
277 |
}
|
278 |
|
279 |
list($expect, $lineno) = array_pop($this->brackets);
|
280 |
if ($this->code[$this->cursor] != strtr($expect, '([{', ')]}')) {
|
281 |
+
throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $lineno, $this->source);
|
282 |
}
|
283 |
}
|
284 |
|
285 |
+
$this->pushToken(Token::PUNCTUATION_TYPE, $this->code[$this->cursor]);
|
286 |
++$this->cursor;
|
287 |
}
|
288 |
// strings
|
289 |
elseif (preg_match(self::REGEX_STRING, $this->code, $match, null, $this->cursor)) {
|
290 |
+
$this->pushToken(Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1)));
|
291 |
$this->moveCursor($match[0]);
|
292 |
}
|
293 |
// opening double quoted string
|
298 |
}
|
299 |
// unlexable
|
300 |
else {
|
301 |
+
throw new SyntaxError(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source);
|
302 |
}
|
303 |
}
|
304 |
|
309 |
}
|
310 |
|
311 |
if (!preg_match(str_replace('%s', $tag, $this->regexes['lex_raw_data']), $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
|
312 |
+
throw new SyntaxError(sprintf('Unexpected end of file: Unclosed "%s" block.', $tag), $this->lineno, $this->source);
|
313 |
}
|
314 |
|
315 |
$text = substr($this->code, $this->cursor, $match[0][1] - $this->cursor);
|
319 |
$text = rtrim($text);
|
320 |
}
|
321 |
|
322 |
+
$this->pushToken(Token::TEXT_TYPE, $text);
|
323 |
}
|
324 |
|
325 |
protected function lexComment()
|
326 |
{
|
327 |
if (!preg_match($this->regexes['lex_comment'], $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
|
328 |
+
throw new SyntaxError('Unclosed comment.', $this->lineno, $this->source);
|
329 |
}
|
330 |
|
331 |
$this->moveCursor(substr($this->code, $this->cursor, $match[0][1] - $this->cursor).$match[0][0]);
|
335 |
{
|
336 |
if (preg_match($this->regexes['interpolation_start'], $this->code, $match, null, $this->cursor)) {
|
337 |
$this->brackets[] = [$this->options['interpolation'][0], $this->lineno];
|
338 |
+
$this->pushToken(Token::INTERPOLATION_START_TYPE);
|
339 |
$this->moveCursor($match[0]);
|
340 |
$this->pushState(self::STATE_INTERPOLATION);
|
341 |
+
} elseif (preg_match(self::REGEX_DQ_STRING_PART, $this->code, $match, null, $this->cursor) && \strlen($match[0]) > 0) {
|
342 |
+
$this->pushToken(Token::STRING_TYPE, stripcslashes($match[0]));
|
343 |
$this->moveCursor($match[0]);
|
344 |
} elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) {
|
345 |
list($expect, $lineno) = array_pop($this->brackets);
|
346 |
if ('"' != $this->code[$this->cursor]) {
|
347 |
+
throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $lineno, $this->source);
|
348 |
}
|
349 |
|
350 |
$this->popState();
|
351 |
++$this->cursor;
|
352 |
} else {
|
353 |
// unlexable
|
354 |
+
throw new SyntaxError(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source);
|
355 |
}
|
356 |
}
|
357 |
|
360 |
$bracket = end($this->brackets);
|
361 |
if ($this->options['interpolation'][0] === $bracket[0] && preg_match($this->regexes['interpolation_end'], $this->code, $match, null, $this->cursor)) {
|
362 |
array_pop($this->brackets);
|
363 |
+
$this->pushToken(Token::INTERPOLATION_END_TYPE);
|
364 |
$this->moveCursor($match[0]);
|
365 |
$this->popState();
|
366 |
} else {
|
371 |
protected function pushToken($type, $value = '')
|
372 |
{
|
373 |
// do not push empty text tokens
|
374 |
+
if (Token::TEXT_TYPE === $type && '' === $value) {
|
375 |
return;
|
376 |
}
|
377 |
|
378 |
+
$this->tokens[] = new Token($type, $value, $this->lineno);
|
379 |
}
|
380 |
|
381 |
protected function moveCursor($text)
|
382 |
{
|
383 |
+
$this->cursor += \strlen($text);
|
384 |
$this->lineno += substr_count($text, "\n");
|
385 |
}
|
386 |
|
422 |
|
423 |
protected function popState()
|
424 |
{
|
425 |
+
if (0 === \count($this->states)) {
|
426 |
+
throw new \LogicException('Cannot pop state without a previous state.');
|
427 |
}
|
428 |
|
429 |
$this->state = array_pop($this->states);
|
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|
|
25 |
-
* @param string
|
26 |
*
|
27 |
-
* @return
|
28 |
*
|
29 |
-
* @throws
|
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 |
}
|
vendor/twig/twig/lib/Twig/Loader/Array.php
CHANGED
@@ -9,6 +9,10 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Loads a template from an array.
|
14 |
*
|
@@ -23,7 +27,7 @@
|
|
23 |
*
|
24 |
* @author Fabien Potencier <fabien@symfony.com>
|
25 |
*/
|
26 |
-
class Twig_Loader_Array implements
|
27 |
{
|
28 |
protected $templates = [];
|
29 |
|
@@ -48,11 +52,11 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
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
|
56 |
}
|
57 |
|
58 |
return $this->templates[$name];
|
@@ -62,10 +66,10 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
62 |
{
|
63 |
$name = (string) $name;
|
64 |
if (!isset($this->templates[$name])) {
|
65 |
-
throw new
|
66 |
}
|
67 |
|
68 |
-
return new
|
69 |
}
|
70 |
|
71 |
public function exists($name)
|
@@ -77,7 +81,7 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
77 |
{
|
78 |
$name = (string) $name;
|
79 |
if (!isset($this->templates[$name])) {
|
80 |
-
throw new
|
81 |
}
|
82 |
|
83 |
return $name.':'.$this->templates[$name];
|
@@ -87,7 +91,7 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
87 |
{
|
88 |
$name = (string) $name;
|
89 |
if (!isset($this->templates[$name])) {
|
90 |
-
throw new
|
91 |
}
|
92 |
|
93 |
return true;
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Error\LoaderError;
|
13 |
+
use Twig\Loader\LoaderInterface;
|
14 |
+
use Twig\Source;
|
15 |
+
|
16 |
/**
|
17 |
* Loads a template from an array.
|
18 |
*
|
27 |
*
|
28 |
* @author Fabien Potencier <fabien@symfony.com>
|
29 |
*/
|
30 |
+
class Twig_Loader_Array implements LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
|
31 |
{
|
32 |
protected $templates = [];
|
33 |
|
52 |
|
53 |
public function getSource($name)
|
54 |
{
|
55 |
+
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', \get_class($this)), E_USER_DEPRECATED);
|
56 |
|
57 |
$name = (string) $name;
|
58 |
if (!isset($this->templates[$name])) {
|
59 |
+
throw new LoaderError(sprintf('Template "%s" is not defined.', $name));
|
60 |
}
|
61 |
|
62 |
return $this->templates[$name];
|
66 |
{
|
67 |
$name = (string) $name;
|
68 |
if (!isset($this->templates[$name])) {
|
69 |
+
throw new LoaderError(sprintf('Template "%s" is not defined.', $name));
|
70 |
}
|
71 |
|
72 |
+
return new Source($this->templates[$name], $name);
|
73 |
}
|
74 |
|
75 |
public function exists($name)
|
81 |
{
|
82 |
$name = (string) $name;
|
83 |
if (!isset($this->templates[$name])) {
|
84 |
+
throw new LoaderError(sprintf('Template "%s" is not defined.', $name));
|
85 |
}
|
86 |
|
87 |
return $name.':'.$this->templates[$name];
|
91 |
{
|
92 |
$name = (string) $name;
|
93 |
if (!isset($this->templates[$name])) {
|
94 |
+
throw new LoaderError(sprintf('Template "%s" is not defined.', $name));
|
95 |
}
|
96 |
|
97 |
return true;
|
vendor/twig/twig/lib/Twig/Loader/Chain.php
CHANGED
@@ -9,6 +9,12 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Loads templates from other loaders.
|
14 |
*
|
@@ -16,13 +22,13 @@
|
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
-
class Twig_Loader_Chain implements
|
20 |
{
|
21 |
private $hasSourceCache = [];
|
22 |
protected $loaders = [];
|
23 |
|
24 |
/**
|
25 |
-
* @param
|
26 |
*/
|
27 |
public function __construct(array $loaders = [])
|
28 |
{
|
@@ -31,7 +37,7 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
31 |
}
|
32 |
}
|
33 |
|
34 |
-
public function addLoader(
|
35 |
{
|
36 |
$this->loaders[] = $loader;
|
37 |
$this->hasSourceCache = [];
|
@@ -39,44 +45,44 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
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
|
47 |
continue;
|
48 |
}
|
49 |
|
50 |
try {
|
51 |
return $loader->getSource($name);
|
52 |
-
} catch (
|
53 |
$exceptions[] = $e->getMessage();
|
54 |
}
|
55 |
}
|
56 |
|
57 |
-
throw new
|
58 |
}
|
59 |
|
60 |
public function getSourceContext($name)
|
61 |
{
|
62 |
$exceptions = [];
|
63 |
foreach ($this->loaders as $loader) {
|
64 |
-
if ($loader instanceof
|
65 |
continue;
|
66 |
}
|
67 |
|
68 |
try {
|
69 |
-
if ($loader instanceof
|
70 |
return $loader->getSourceContext($name);
|
71 |
}
|
72 |
|
73 |
-
return new
|
74 |
-
} catch (
|
75 |
$exceptions[] = $e->getMessage();
|
76 |
}
|
77 |
}
|
78 |
|
79 |
-
throw new
|
80 |
}
|
81 |
|
82 |
public function exists($name)
|
@@ -88,7 +94,7 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
88 |
}
|
89 |
|
90 |
foreach ($this->loaders as $loader) {
|
91 |
-
if ($loader instanceof
|
92 |
if ($loader->exists($name)) {
|
93 |
return $this->hasSourceCache[$name] = true;
|
94 |
}
|
@@ -97,14 +103,14 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
97 |
}
|
98 |
|
99 |
try {
|
100 |
-
if ($loader instanceof
|
101 |
$loader->getSourceContext($name);
|
102 |
} else {
|
103 |
$loader->getSource($name);
|
104 |
}
|
105 |
|
106 |
return $this->hasSourceCache[$name] = true;
|
107 |
-
} catch (
|
108 |
}
|
109 |
}
|
110 |
|
@@ -115,36 +121,36 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|
115 |
{
|
116 |
$exceptions = [];
|
117 |
foreach ($this->loaders as $loader) {
|
118 |
-
if ($loader instanceof
|
119 |
continue;
|
120 |
}
|
121 |
|
122 |
try {
|
123 |
return $loader->getCacheKey($name);
|
124 |
-
} catch (
|
125 |
-
$exceptions[] = get_class($loader).': '.$e->getMessage();
|
126 |
}
|
127 |
}
|
128 |
|
129 |
-
throw new
|
130 |
}
|
131 |
|
132 |
public function isFresh($name, $time)
|
133 |
{
|
134 |
$exceptions = [];
|
135 |
foreach ($this->loaders as $loader) {
|
136 |
-
if ($loader instanceof
|
137 |
continue;
|
138 |
}
|
139 |
|
140 |
try {
|
141 |
return $loader->isFresh($name, $time);
|
142 |
-
} catch (
|
143 |
-
$exceptions[] = get_class($loader).': '.$e->getMessage();
|
144 |
}
|
145 |
}
|
146 |
|
147 |
-
throw new
|
148 |
}
|
149 |
}
|
150 |
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Error\LoaderError;
|
13 |
+
use Twig\Loader\ExistsLoaderInterface;
|
14 |
+
use Twig\Loader\LoaderInterface;
|
15 |
+
use Twig\Loader\SourceContextLoaderInterface;
|
16 |
+
use Twig\Source;
|
17 |
+
|
18 |
/**
|
19 |
* Loads templates from other loaders.
|
20 |
*
|
22 |
*
|
23 |
* @author Fabien Potencier <fabien@symfony.com>
|
24 |
*/
|
25 |
+
class Twig_Loader_Chain implements LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
|
26 |
{
|
27 |
private $hasSourceCache = [];
|
28 |
protected $loaders = [];
|
29 |
|
30 |
/**
|
31 |
+
* @param LoaderInterface[] $loaders
|
32 |
*/
|
33 |
public function __construct(array $loaders = [])
|
34 |
{
|
37 |
}
|
38 |
}
|
39 |
|
40 |
+
public function addLoader(LoaderInterface $loader)
|
41 |
{
|
42 |
$this->loaders[] = $loader;
|
43 |
$this->hasSourceCache = [];
|
45 |
|
46 |
public function getSource($name)
|
47 |
{
|
48 |
+
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', \get_class($this)), E_USER_DEPRECATED);
|
49 |
|
50 |
$exceptions = [];
|
51 |
foreach ($this->loaders as $loader) {
|
52 |
+
if ($loader instanceof ExistsLoaderInterface && !$loader->exists($name)) {
|
53 |
continue;
|
54 |
}
|
55 |
|
56 |
try {
|
57 |
return $loader->getSource($name);
|
58 |
+
} catch (LoaderError $e) {
|
59 |
$exceptions[] = $e->getMessage();
|
60 |
}
|
61 |
}
|
62 |
|
63 |
+
throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
|
64 |
}
|
65 |
|
66 |
public function getSourceContext($name)
|
67 |
{
|
68 |
$exceptions = [];
|
69 |
foreach ($this->loaders as $loader) {
|
70 |
+
if ($loader instanceof ExistsLoaderInterface && !$loader->exists($name)) {
|
71 |
continue;
|
72 |
}
|
73 |
|
74 |
try {
|
75 |
+
if ($loader instanceof SourceContextLoaderInterface) {
|
76 |
return $loader->getSourceContext($name);
|
77 |
}
|
78 |
|
79 |
+
return new Source($loader->getSource($name), $name);
|
80 |
+
} catch (LoaderError $e) {
|
81 |
$exceptions[] = $e->getMessage();
|
82 |
}
|
83 |
}
|
84 |
|
85 |
+
throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
|
86 |
}
|
87 |
|
88 |
public function exists($name)
|
94 |
}
|
95 |
|
96 |
foreach ($this->loaders as $loader) {
|
97 |
+
if ($loader instanceof ExistsLoaderInterface) {
|
98 |
if ($loader->exists($name)) {
|
99 |
return $this->hasSourceCache[$name] = true;
|
100 |
}
|
103 |
}
|
104 |
|
105 |
try {
|
106 |
+
if ($loader instanceof SourceContextLoaderInterface) {
|
107 |
$loader->getSourceContext($name);
|
108 |
} else {
|
109 |
$loader->getSource($name);
|
110 |
}
|
111 |
|
112 |
return $this->hasSourceCache[$name] = true;
|
113 |
+
} catch (LoaderError $e) {
|
114 |
}
|
115 |
}
|
116 |
|
121 |
{
|
122 |
$exceptions = [];
|
123 |
foreach ($this->loaders as $loader) {
|
124 |
+
if ($loader instanceof ExistsLoaderInterface && !$loader->exists($name)) {
|
125 |
continue;
|
126 |
}
|
127 |
|
128 |
try {
|
129 |
return $loader->getCacheKey($name);
|
130 |
+
} catch (LoaderError $e) {
|
131 |
+
$exceptions[] = \get_class($loader).': '.$e->getMessage();
|
132 |
}
|
133 |
}
|
134 |
|
135 |
+
throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
|
136 |
}
|
137 |
|
138 |
public function isFresh($name, $time)
|
139 |
{
|
140 |
$exceptions = [];
|
141 |
foreach ($this->loaders as $loader) {
|
142 |
+
if ($loader instanceof ExistsLoaderInterface && !$loader->exists($name)) {
|
143 |
continue;
|
144 |
}
|
145 |
|
146 |
try {
|
147 |
return $loader->isFresh($name, $time);
|
148 |
+
} catch (LoaderError $e) {
|
149 |
+
$exceptions[] = \get_class($loader).': '.$e->getMessage();
|
150 |
}
|
151 |
}
|
152 |
|
153 |
+
throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
|
154 |
}
|
155 |
}
|
156 |
|
vendor/twig/twig/lib/Twig/Loader/Filesystem.php
CHANGED
@@ -9,12 +9,16 @@
|
|
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
|
18 |
{
|
19 |
/** Identifier of the main namespace. */
|
20 |
const MAIN_NAMESPACE = '__main__';
|
@@ -73,7 +77,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
73 |
*/
|
74 |
public function setPaths($paths, $namespace = self::MAIN_NAMESPACE)
|
75 |
{
|
76 |
-
if (
|
77 |
$paths = [$paths];
|
78 |
}
|
79 |
|
@@ -89,7 +93,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
89 |
* @param string $path A path where to look for templates
|
90 |
* @param string $namespace A path namespace
|
91 |
*
|
92 |
-
* @throws
|
93 |
*/
|
94 |
public function addPath($path, $namespace = self::MAIN_NAMESPACE)
|
95 |
{
|
@@ -98,7 +102,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
98 |
|
99 |
$checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path;
|
100 |
if (!is_dir($checkPath)) {
|
101 |
-
throw new
|
102 |
}
|
103 |
|
104 |
$this->paths[$namespace][] = rtrim($path, '/\\');
|
@@ -110,7 +114,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
110 |
* @param string $path A path where to look for templates
|
111 |
* @param string $namespace A path namespace
|
112 |
*
|
113 |
-
* @throws
|
114 |
*/
|
115 |
public function prependPath($path, $namespace = self::MAIN_NAMESPACE)
|
116 |
{
|
@@ -119,7 +123,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
119 |
|
120 |
$checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path;
|
121 |
if (!is_dir($checkPath)) {
|
122 |
-
throw new
|
123 |
}
|
124 |
|
125 |
$path = rtrim($path, '/\\');
|
@@ -133,7 +137,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
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 |
}
|
@@ -142,13 +146,13 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
142 |
{
|
143 |
$path = $this->findTemplate($name);
|
144 |
|
145 |
-
return new
|
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 |
}
|
@@ -166,8 +170,8 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
166 |
|
167 |
try {
|
168 |
return false !== $this->findTemplate($name, false);
|
169 |
-
} catch (
|
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 |
}
|
@@ -180,7 +184,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
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])) {
|
@@ -192,14 +196,14 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
192 |
return false;
|
193 |
}
|
194 |
|
195 |
-
throw new
|
196 |
}
|
197 |
|
198 |
try {
|
199 |
$this->validateName($name);
|
200 |
|
201 |
list($namespace, $shortname) = $this->parseName($name);
|
202 |
-
} catch (
|
203 |
if (!$throw) {
|
204 |
return false;
|
205 |
}
|
@@ -214,12 +218,12 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
214 |
return false;
|
215 |
}
|
216 |
|
217 |
-
throw new
|
218 |
}
|
219 |
|
220 |
foreach ($this->paths[$namespace] as $path) {
|
221 |
if (!$this->isAbsolutePath($path)) {
|
222 |
-
$path = $this->rootPath
|
223 |
}
|
224 |
|
225 |
if (is_file($path.'/'.$shortname)) {
|
@@ -237,14 +241,14 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
237 |
return false;
|
238 |
}
|
239 |
|
240 |
-
throw new
|
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
|
248 |
}
|
249 |
|
250 |
$namespace = substr($name, 1, $pos - 1);
|
@@ -264,7 +268,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
264 |
protected function validateName($name)
|
265 |
{
|
266 |
if (false !== strpos($name, "\0")) {
|
267 |
-
throw new
|
268 |
}
|
269 |
|
270 |
$name = ltrim($name, '/');
|
@@ -278,7 +282,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
278 |
}
|
279 |
|
280 |
if ($level < 0) {
|
281 |
-
throw new
|
282 |
}
|
283 |
}
|
284 |
}
|
@@ -286,7 +290,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|
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 |
)
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Error\LoaderError;
|
13 |
+
use Twig\Loader\LoaderInterface;
|
14 |
+
use Twig\Source;
|
15 |
+
|
16 |
/**
|
17 |
* Loads template from the filesystem.
|
18 |
*
|
19 |
* @author Fabien Potencier <fabien@symfony.com>
|
20 |
*/
|
21 |
+
class Twig_Loader_Filesystem implements LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
|
22 |
{
|
23 |
/** Identifier of the main namespace. */
|
24 |
const MAIN_NAMESPACE = '__main__';
|
77 |
*/
|
78 |
public function setPaths($paths, $namespace = self::MAIN_NAMESPACE)
|
79 |
{
|
80 |
+
if (!\is_array($paths)) {
|
81 |
$paths = [$paths];
|
82 |
}
|
83 |
|
93 |
* @param string $path A path where to look for templates
|
94 |
* @param string $namespace A path namespace
|
95 |
*
|
96 |
+
* @throws LoaderError
|
97 |
*/
|
98 |
public function addPath($path, $namespace = self::MAIN_NAMESPACE)
|
99 |
{
|
102 |
|
103 |
$checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path;
|
104 |
if (!is_dir($checkPath)) {
|
105 |
+
throw new LoaderError(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath));
|
106 |
}
|
107 |
|
108 |
$this->paths[$namespace][] = rtrim($path, '/\\');
|
114 |
* @param string $path A path where to look for templates
|
115 |
* @param string $namespace A path namespace
|
116 |
*
|
117 |
+
* @throws LoaderError
|
118 |
*/
|
119 |
public function prependPath($path, $namespace = self::MAIN_NAMESPACE)
|
120 |
{
|
123 |
|
124 |
$checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path;
|
125 |
if (!is_dir($checkPath)) {
|
126 |
+
throw new LoaderError(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath));
|
127 |
}
|
128 |
|
129 |
$path = rtrim($path, '/\\');
|
137 |
|
138 |
public function getSource($name)
|
139 |
{
|
140 |
+
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', \get_class($this)), E_USER_DEPRECATED);
|
141 |
|
142 |
return file_get_contents($this->findTemplate($name));
|
143 |
}
|
146 |
{
|
147 |
$path = $this->findTemplate($name);
|
148 |
|
149 |
+
return new Source(file_get_contents($path), $name, $path);
|
150 |
}
|
151 |
|
152 |
public function getCacheKey($name)
|
153 |
{
|
154 |
$path = $this->findTemplate($name);
|
155 |
+
$len = \strlen($this->rootPath);
|
156 |
if (0 === strncmp($this->rootPath, $path, $len)) {
|
157 |
return substr($path, $len);
|
158 |
}
|
170 |
|
171 |
try {
|
172 |
return false !== $this->findTemplate($name, false);
|
173 |
+
} catch (LoaderError $exception) {
|
174 |
+
@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);
|
175 |
|
176 |
return false;
|
177 |
}
|
184 |
|
185 |
protected function findTemplate($name)
|
186 |
{
|
187 |
+
$throw = \func_num_args() > 1 ? func_get_arg(1) : true;
|
188 |
$name = $this->normalizeName($name);
|
189 |
|
190 |
if (isset($this->cache[$name])) {
|
196 |
return false;
|
197 |
}
|
198 |
|
199 |
+
throw new LoaderError($this->errorCache[$name]);
|
200 |
}
|
201 |
|
202 |
try {
|
203 |
$this->validateName($name);
|
204 |
|
205 |
list($namespace, $shortname) = $this->parseName($name);
|
206 |
+
} catch (LoaderError $e) {
|
207 |
if (!$throw) {
|
208 |
return false;
|
209 |
}
|
218 |
return false;
|
219 |
}
|
220 |
|
221 |
+
throw new LoaderError($this->errorCache[$name]);
|
222 |
}
|
223 |
|
224 |
foreach ($this->paths[$namespace] as $path) {
|
225 |
if (!$this->isAbsolutePath($path)) {
|
226 |
+
$path = $this->rootPath.$path;
|
227 |
}
|
228 |
|
229 |
if (is_file($path.'/'.$shortname)) {
|
241 |
return false;
|
242 |
}
|
243 |
|
244 |
+
throw new LoaderError($this->errorCache[$name]);
|
245 |
}
|
246 |
|
247 |
protected function parseName($name, $default = self::MAIN_NAMESPACE)
|
248 |
{
|
249 |
if (isset($name[0]) && '@' == $name[0]) {
|
250 |
if (false === $pos = strpos($name, '/')) {
|
251 |
+
throw new LoaderError(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
|
252 |
}
|
253 |
|
254 |
$namespace = substr($name, 1, $pos - 1);
|
268 |
protected function validateName($name)
|
269 |
{
|
270 |
if (false !== strpos($name, "\0")) {
|
271 |
+
throw new LoaderError('A template name cannot contain NUL bytes.');
|
272 |
}
|
273 |
|
274 |
$name = ltrim($name, '/');
|
282 |
}
|
283 |
|
284 |
if ($level < 0) {
|
285 |
+
throw new LoaderError(sprintf('Looks like you try to load a template outside configured directories (%s).', $name));
|
286 |
}
|
287 |
}
|
288 |
}
|
290 |
private function isAbsolutePath($file)
|
291 |
{
|
292 |
return strspn($file, '/\\', 0, 1)
|
293 |
+
|| (\strlen($file) > 3 && ctype_alpha($file[0])
|
294 |
&& ':' === substr($file, 1, 1)
|
295 |
&& strspn($file, '/\\', 2, 1)
|
296 |
)
|
vendor/twig/twig/lib/Twig/Loader/String.php
CHANGED
@@ -9,7 +9,10 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
-
|
|
|
|
|
|
|
13 |
|
14 |
/**
|
15 |
* Loads a template from a string.
|
@@ -27,18 +30,18 @@
|
|
27 |
*
|
28 |
* @author Fabien Potencier <fabien@symfony.com>
|
29 |
*/
|
30 |
-
class Twig_Loader_String implements
|
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
|
42 |
}
|
43 |
|
44 |
public function exists($name)
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Loader\LoaderInterface;
|
13 |
+
use Twig\Source;
|
14 |
+
|
15 |
+
@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);
|
16 |
|
17 |
/**
|
18 |
* Loads a template from a string.
|
30 |
*
|
31 |
* @author Fabien Potencier <fabien@symfony.com>
|
32 |
*/
|
33 |
+
class Twig_Loader_String implements LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface
|
34 |
{
|
35 |
public function getSource($name)
|
36 |
{
|
37 |
+
@trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', \get_class($this)), E_USER_DEPRECATED);
|
38 |
|
39 |
return $name;
|
40 |
}
|
41 |
|
42 |
public function getSourceContext($name)
|
43 |
{
|
44 |
+
return new Source($name, $name);
|
45 |
}
|
46 |
|
47 |
public function exists($name)
|
vendor/twig/twig/lib/Twig/LoaderInterface.php
CHANGED
@@ -9,6 +9,8 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
12 |
/**
|
13 |
* Interface all loaders must implement.
|
14 |
*
|
@@ -23,7 +25,7 @@ interface Twig_LoaderInterface
|
|
23 |
*
|
24 |
* @return string The template source code
|
25 |
*
|
26 |
-
* @throws
|
27 |
*
|
28 |
* @deprecated since 1.27 (to be removed in 2.0), implement Twig_SourceContextLoaderInterface
|
29 |
*/
|
@@ -36,7 +38,7 @@ interface Twig_LoaderInterface
|
|
36 |
*
|
37 |
* @return string The cache key
|
38 |
*
|
39 |
-
* @throws
|
40 |
*/
|
41 |
public function getCacheKey($name);
|
42 |
|
@@ -49,7 +51,7 @@ interface Twig_LoaderInterface
|
|
49 |
*
|
50 |
* @return bool true if the template is fresh, false otherwise
|
51 |
*
|
52 |
-
* @throws
|
53 |
*/
|
54 |
public function isFresh($name, $time);
|
55 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Error\LoaderError;
|
13 |
+
|
14 |
/**
|
15 |
* Interface all loaders must implement.
|
16 |
*
|
25 |
*
|
26 |
* @return string The template source code
|
27 |
*
|
28 |
+
* @throws LoaderError When $name is not found
|
29 |
*
|
30 |
* @deprecated since 1.27 (to be removed in 2.0), implement Twig_SourceContextLoaderInterface
|
31 |
*/
|
38 |
*
|
39 |
* @return string The cache key
|
40 |
*
|
41 |
+
* @throws LoaderError When $name is not found
|
42 |
*/
|
43 |
public function getCacheKey($name);
|
44 |
|
51 |
*
|
52 |
* @return bool true if the template is fresh, false otherwise
|
53 |
*
|
54 |
+
* @throws LoaderError When $name is not found
|
55 |
*/
|
56 |
public function isFresh($name, $time);
|
57 |
}
|
vendor/twig/twig/lib/Twig/Markup.php
CHANGED
@@ -14,7 +14,7 @@
|
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
*/
|
17 |
-
class Twig_Markup implements Countable
|
18 |
{
|
19 |
protected $content;
|
20 |
protected $charset;
|
@@ -32,7 +32,7 @@ class Twig_Markup implements Countable
|
|
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 |
|
14 |
*
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
*/
|
17 |
+
class Twig_Markup implements \Countable
|
18 |
{
|
19 |
protected $content;
|
20 |
protected $charset;
|
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 |
|
vendor/twig/twig/lib/Twig/Node.php
CHANGED
@@ -10,6 +10,9 @@
|
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
|
|
|
|
|
|
13 |
/**
|
14 |
* Represents a node in the AST.
|
15 |
*
|
@@ -39,7 +42,7 @@ class Twig_Node implements Twig_NodeInterface
|
|
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;
|
@@ -55,11 +58,11 @@ class Twig_Node implements Twig_NodeInterface
|
|
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;
|
@@ -83,12 +86,12 @@ class Twig_Node implements Twig_NodeInterface
|
|
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'));
|
@@ -111,7 +114,7 @@ class Twig_Node implements Twig_NodeInterface
|
|
111 |
return $asDom ? $dom : $dom->saveXML();
|
112 |
}
|
113 |
|
114 |
-
public function compile(
|
115 |
{
|
116 |
foreach ($this->nodes as $node) {
|
117 |
$node->compile($compiler);
|
@@ -143,7 +146,7 @@ class Twig_Node implements Twig_NodeInterface
|
|
143 |
*/
|
144 |
public function hasAttribute($name)
|
145 |
{
|
146 |
-
return array_key_exists($name, $this->attributes);
|
147 |
}
|
148 |
|
149 |
/**
|
@@ -151,8 +154,8 @@ class Twig_Node implements Twig_NodeInterface
|
|
151 |
*/
|
152 |
public function getAttribute($name)
|
153 |
{
|
154 |
-
if (
|
155 |
-
throw new LogicException(sprintf('Attribute "%s" does not exist for Node "%s".', $name, get_class($this)));
|
156 |
}
|
157 |
|
158 |
return $this->attributes[$name];
|
@@ -177,16 +180,16 @@ class Twig_Node implements Twig_NodeInterface
|
|
177 |
*/
|
178 |
public function hasNode($name)
|
179 |
{
|
180 |
-
return array_key_exists($name, $this->nodes);
|
181 |
}
|
182 |
|
183 |
/**
|
184 |
-
* @return
|
185 |
*/
|
186 |
public function getNode($name)
|
187 |
{
|
188 |
-
if (
|
189 |
-
throw new LogicException(sprintf('Node "%s" does not exist for Node "%s".', $name, get_class($this)));
|
190 |
}
|
191 |
|
192 |
return $this->nodes[$name];
|
@@ -195,7 +198,7 @@ class Twig_Node implements Twig_NodeInterface
|
|
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;
|
@@ -208,12 +211,12 @@ class Twig_Node implements Twig_NodeInterface
|
|
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)
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Node;
|
15 |
+
|
16 |
/**
|
17 |
* Represents a node in the AST.
|
18 |
*
|
42 |
{
|
43 |
foreach ($nodes as $name => $node) {
|
44 |
if (!$node instanceof Twig_NodeInterface) {
|
45 |
+
@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);
|
46 |
}
|
47 |
}
|
48 |
$this->nodes = $nodes;
|
58 |
$attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true)));
|
59 |
}
|
60 |
|
61 |
+
$repr = [\get_class($this).'('.implode(', ', $attributes)];
|
62 |
|
63 |
+
if (\count($this->nodes)) {
|
64 |
foreach ($this->nodes as $name => $node) {
|
65 |
+
$len = \strlen($name) + 4;
|
66 |
$noderepr = [];
|
67 |
foreach (explode("\n", (string) $node) as $line) {
|
68 |
$noderepr[] = str_repeat(' ', $len).$line;
|
86 |
{
|
87 |
@trigger_error(sprintf('%s is deprecated since version 1.16.1 and will be removed in 2.0.', __METHOD__), E_USER_DEPRECATED);
|
88 |
|
89 |
+
$dom = new \DOMDocument('1.0', 'UTF-8');
|
90 |
$dom->formatOutput = true;
|
91 |
$dom->appendChild($xml = $dom->createElement('twig'));
|
92 |
|
93 |
$xml->appendChild($node = $dom->createElement('node'));
|
94 |
+
$node->setAttribute('class', \get_class($this));
|
95 |
|
96 |
foreach ($this->attributes as $name => $value) {
|
97 |
$node->appendChild($attribute = $dom->createElement('attribute'));
|
114 |
return $asDom ? $dom : $dom->saveXML();
|
115 |
}
|
116 |
|
117 |
+
public function compile(Compiler $compiler)
|
118 |
{
|
119 |
foreach ($this->nodes as $node) {
|
120 |
$node->compile($compiler);
|
146 |
*/
|
147 |
public function hasAttribute($name)
|
148 |
{
|
149 |
+
return \array_key_exists($name, $this->attributes);
|
150 |
}
|
151 |
|
152 |
/**
|
154 |
*/
|
155 |
public function getAttribute($name)
|
156 |
{
|
157 |
+
if (!\array_key_exists($name, $this->attributes)) {
|
158 |
+
throw new \LogicException(sprintf('Attribute "%s" does not exist for Node "%s".', $name, \get_class($this)));
|
159 |
}
|
160 |
|
161 |
return $this->attributes[$name];
|
180 |
*/
|
181 |
public function hasNode($name)
|
182 |
{
|
183 |
+
return \array_key_exists($name, $this->nodes);
|
184 |
}
|
185 |
|
186 |
/**
|
187 |
+
* @return Node
|
188 |
*/
|
189 |
public function getNode($name)
|
190 |
{
|
191 |
+
if (!\array_key_exists($name, $this->nodes)) {
|
192 |
+
throw new \LogicException(sprintf('Node "%s" does not exist for Node "%s".', $name, \get_class($this)));
|
193 |
}
|
194 |
|
195 |
return $this->nodes[$name];
|
198 |
public function setNode($name, $node = null)
|
199 |
{
|
200 |
if (!$node instanceof Twig_NodeInterface) {
|
201 |
+
@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);
|
202 |
}
|
203 |
|
204 |
$this->nodes[$name] = $node;
|
211 |
|
212 |
public function count()
|
213 |
{
|
214 |
+
return \count($this->nodes);
|
215 |
}
|
216 |
|
217 |
public function getIterator()
|
218 |
{
|
219 |
+
return new \ArrayIterator($this->nodes);
|
220 |
}
|
221 |
|
222 |
public function setTemplateName($name)
|
vendor/twig/twig/lib/Twig/Node/AutoEscape.php
CHANGED
@@ -9,6 +9,9 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Represents an autoescape node.
|
14 |
*
|
@@ -20,14 +23,14 @@
|
|
20 |
*
|
21 |
* @author Fabien Potencier <fabien@symfony.com>
|
22 |
*/
|
23 |
-
class Twig_Node_AutoEscape extends
|
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(
|
31 |
{
|
32 |
$compiler->subcompile($this->getNode('body'));
|
33 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Node;
|
14 |
+
|
15 |
/**
|
16 |
* Represents an autoescape node.
|
17 |
*
|
23 |
*
|
24 |
* @author Fabien Potencier <fabien@symfony.com>
|
25 |
*/
|
26 |
+
class Twig_Node_AutoEscape extends Node
|
27 |
{
|
28 |
public function __construct($value, Twig_NodeInterface $body, $lineno, $tag = 'autoescape')
|
29 |
{
|
30 |
parent::__construct(['body' => $body], ['value' => $value], $lineno, $tag);
|
31 |
}
|
32 |
|
33 |
+
public function compile(Compiler $compiler)
|
34 |
{
|
35 |
$compiler->subcompile($this->getNode('body'));
|
36 |
}
|
vendor/twig/twig/lib/Twig/Node/Block.php
CHANGED
@@ -10,19 +10,22 @@
|
|
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
|
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(
|
26 |
{
|
27 |
$compiler
|
28 |
->addDebugInfo($this)
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Node;
|
15 |
+
|
16 |
/**
|
17 |
* Represents a block node.
|
18 |
*
|
19 |
* @author Fabien Potencier <fabien@symfony.com>
|
20 |
*/
|
21 |
+
class Twig_Node_Block extends Node
|
22 |
{
|
23 |
public function __construct($name, Twig_NodeInterface $body, $lineno, $tag = null)
|
24 |
{
|
25 |
parent::__construct(['body' => $body], ['name' => $name], $lineno, $tag);
|
26 |
}
|
27 |
|
28 |
+
public function compile(Compiler $compiler)
|
29 |
{
|
30 |
$compiler
|
31 |
->addDebugInfo($this)
|
vendor/twig/twig/lib/Twig/Node/BlockReference.php
CHANGED
@@ -10,19 +10,23 @@
|
|
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
|
19 |
{
|
20 |
public function __construct($name, $lineno, $tag = null)
|
21 |
{
|
22 |
parent::__construct([], ['name' => $name], $lineno, $tag);
|
23 |
}
|
24 |
|
25 |
-
public function compile(
|
26 |
{
|
27 |
$compiler
|
28 |
->addDebugInfo($this)
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Node;
|
15 |
+
use Twig\Node\NodeOutputInterface;
|
16 |
+
|
17 |
/**
|
18 |
* Represents a block call node.
|
19 |
*
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
+
class Twig_Node_BlockReference extends Node implements NodeOutputInterface
|
23 |
{
|
24 |
public function __construct($name, $lineno, $tag = null)
|
25 |
{
|
26 |
parent::__construct([], ['name' => $name], $lineno, $tag);
|
27 |
}
|
28 |
|
29 |
+
public function compile(Compiler $compiler)
|
30 |
{
|
31 |
$compiler
|
32 |
->addDebugInfo($this)
|
vendor/twig/twig/lib/Twig/Node/Body.php
CHANGED
@@ -9,12 +9,14 @@
|
|
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
|
18 |
{
|
19 |
}
|
20 |
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Node\Node;
|
13 |
+
|
14 |
/**
|
15 |
* Represents a body node.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
+
class Twig_Node_Body extends Node
|
20 |
{
|
21 |
}
|
22 |
|
vendor/twig/twig/lib/Twig/Node/CheckSecurity.php
CHANGED
@@ -9,10 +9,13 @@
|
|
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
|
16 |
{
|
17 |
protected $usedFilters;
|
18 |
protected $usedTags;
|
@@ -27,12 +30,12 @@ class Twig_Node_CheckSecurity extends Twig_Node
|
|
27 |
parent::__construct();
|
28 |
}
|
29 |
|
30 |
-
public function compile(
|
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
|
36 |
${$type}[$name] = $node->getTemplateLine();
|
37 |
} else {
|
38 |
${$type}[$node] = null;
|
@@ -46,7 +49,7 @@ class Twig_Node_CheckSecurity extends Twig_Node
|
|
46 |
->write('$functions = ')->repr(array_filter($functions))->raw(";\n\n")
|
47 |
->write("try {\n")
|
48 |
->indent()
|
49 |
-
->write("\$this->env->getExtension('
|
50 |
->indent()
|
51 |
->write(!$tags ? "[],\n" : "['".implode("', '", array_keys($tags))."'],\n")
|
52 |
->write(!$filters ? "[],\n" : "['".implode("', '", array_keys($filters))."'],\n")
|
@@ -54,18 +57,18 @@ class Twig_Node_CheckSecurity extends Twig_Node
|
|
54 |
->outdent()
|
55 |
->write(");\n")
|
56 |
->outdent()
|
57 |
-
->write("} catch (
|
58 |
->indent()
|
59 |
->write("\$e->setSourceContext(\$this->getSourceContext());\n\n")
|
60 |
-
->write("if (\$e instanceof
|
61 |
->indent()
|
62 |
->write("\$e->setTemplateLine(\$tags[\$e->getTagName()]);\n")
|
63 |
->outdent()
|
64 |
-
->write("} elseif (\$e instanceof
|
65 |
->indent()
|
66 |
->write("\$e->setTemplateLine(\$filters[\$e->getFilterName()]);\n")
|
67 |
->outdent()
|
68 |
-
->write("} elseif (\$e instanceof
|
69 |
->indent()
|
70 |
->write("\$e->setTemplateLine(\$functions[\$e->getFunctionName()]);\n")
|
71 |
->outdent()
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Node;
|
14 |
+
|
15 |
/**
|
16 |
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*/
|
18 |
+
class Twig_Node_CheckSecurity extends Node
|
19 |
{
|
20 |
protected $usedFilters;
|
21 |
protected $usedTags;
|
30 |
parent::__construct();
|
31 |
}
|
32 |
|
33 |
+
public function compile(Compiler $compiler)
|
34 |
{
|
35 |
$tags = $filters = $functions = [];
|
36 |
foreach (['tags', 'filters', 'functions'] as $type) {
|
37 |
foreach ($this->{'used'.ucfirst($type)} as $name => $node) {
|
38 |
+
if ($node instanceof Node) {
|
39 |
${$type}[$name] = $node->getTemplateLine();
|
40 |
} else {
|
41 |
${$type}[$node] = null;
|
49 |
->write('$functions = ')->repr(array_filter($functions))->raw(";\n\n")
|
50 |
->write("try {\n")
|
51 |
->indent()
|
52 |
+
->write("\$this->env->getExtension('\Twig\Extension\SandboxExtension')->checkSecurity(\n")
|
53 |
->indent()
|
54 |
->write(!$tags ? "[],\n" : "['".implode("', '", array_keys($tags))."'],\n")
|
55 |
->write(!$filters ? "[],\n" : "['".implode("', '", array_keys($filters))."'],\n")
|
57 |
->outdent()
|
58 |
->write(");\n")
|
59 |
->outdent()
|
60 |
+
->write("} catch (SecurityError \$e) {\n")
|
61 |
->indent()
|
62 |
->write("\$e->setSourceContext(\$this->getSourceContext());\n\n")
|
63 |
+
->write("if (\$e instanceof SecurityNotAllowedTagError && isset(\$tags[\$e->getTagName()])) {\n")
|
64 |
->indent()
|
65 |
->write("\$e->setTemplateLine(\$tags[\$e->getTagName()]);\n")
|
66 |
->outdent()
|
67 |
+
->write("} elseif (\$e instanceof SecurityNotAllowedFilterError && isset(\$filters[\$e->getFilterName()])) {\n")
|
68 |
->indent()
|
69 |
->write("\$e->setTemplateLine(\$filters[\$e->getFilterName()]);\n")
|
70 |
->outdent()
|
71 |
+
->write("} elseif (\$e instanceof SecurityNotAllowedFunctionError && isset(\$functions[\$e->getFunctionName()])) {\n")
|
72 |
->indent()
|
73 |
->write("\$e->setTemplateLine(\$functions[\$e->getFunctionName()]);\n")
|
74 |
->outdent()
|
vendor/twig/twig/lib/Twig/Node/Deprecated.php
CHANGED
@@ -9,25 +9,30 @@
|
|
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
|
18 |
{
|
19 |
-
public function __construct(
|
20 |
{
|
21 |
parent::__construct(['expr' => $expr], [], $lineno, $tag);
|
22 |
}
|
23 |
|
24 |
-
public function compile(
|
25 |
{
|
26 |
$compiler->addDebugInfo($this);
|
27 |
|
28 |
$expr = $this->getNode('expr');
|
29 |
|
30 |
-
if ($expr instanceof
|
31 |
$compiler->write('@trigger_error(')
|
32 |
->subcompile($expr);
|
33 |
} else {
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\AbstractExpression;
|
14 |
+
use Twig\Node\Expression\ConstantExpression;
|
15 |
+
use Twig\Node\Node;
|
16 |
+
|
17 |
/**
|
18 |
* Represents a deprecated node.
|
19 |
*
|
20 |
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
21 |
*/
|
22 |
+
class Twig_Node_Deprecated extends Node
|
23 |
{
|
24 |
+
public function __construct(AbstractExpression $expr, $lineno, $tag = null)
|
25 |
{
|
26 |
parent::__construct(['expr' => $expr], [], $lineno, $tag);
|
27 |
}
|
28 |
|
29 |
+
public function compile(Compiler $compiler)
|
30 |
{
|
31 |
$compiler->addDebugInfo($this);
|
32 |
|
33 |
$expr = $this->getNode('expr');
|
34 |
|
35 |
+
if ($expr instanceof ConstantExpression) {
|
36 |
$compiler->write('@trigger_error(')
|
37 |
->subcompile($expr);
|
38 |
} else {
|
vendor/twig/twig/lib/Twig/Node/Do.php
CHANGED
@@ -9,19 +9,23 @@
|
|
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
|
18 |
{
|
19 |
-
public function __construct(
|
20 |
{
|
21 |
parent::__construct(['expr' => $expr], [], $lineno, $tag);
|
22 |
}
|
23 |
|
24 |
-
public function compile(
|
25 |
{
|
26 |
$compiler
|
27 |
->addDebugInfo($this)
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\AbstractExpression;
|
14 |
+
use Twig\Node\Node;
|
15 |
+
|
16 |
/**
|
17 |
* Represents a do node.
|
18 |
*
|
19 |
* @author Fabien Potencier <fabien@symfony.com>
|
20 |
*/
|
21 |
+
class Twig_Node_Do extends Node
|
22 |
{
|
23 |
+
public function __construct(AbstractExpression $expr, $lineno, $tag = null)
|
24 |
{
|
25 |
parent::__construct(['expr' => $expr], [], $lineno, $tag);
|
26 |
}
|
27 |
|
28 |
+
public function compile(Compiler $compiler)
|
29 |
{
|
30 |
$compiler
|
31 |
->addDebugInfo($this)
|
vendor/twig/twig/lib/Twig/Node/Embed.php
CHANGED
@@ -9,17 +9,22 @@
|
|
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
|
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,
|
21 |
{
|
22 |
-
parent::__construct(new
|
23 |
|
24 |
$this->setAttribute('name', $name);
|
25 |
// to be removed in 2.0, used name instead
|
@@ -27,7 +32,7 @@ class Twig_Node_Embed extends Twig_Node_Include
|
|
27 |
$this->setAttribute('index', $index);
|
28 |
}
|
29 |
|
30 |
-
protected function addGetTemplate(
|
31 |
{
|
32 |
$compiler
|
33 |
->write('$this->loadTemplate(')
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\AbstractExpression;
|
14 |
+
use Twig\Node\Expression\ConstantExpression;
|
15 |
+
use Twig\Node\IncludeNode;
|
16 |
+
|
17 |
/**
|
18 |
* Represents an embed node.
|
19 |
*
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
+
class Twig_Node_Embed extends IncludeNode
|
23 |
{
|
24 |
// we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module)
|
25 |
+
public function __construct($name, $index, AbstractExpression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
|
26 |
{
|
27 |
+
parent::__construct(new ConstantExpression('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag);
|
28 |
|
29 |
$this->setAttribute('name', $name);
|
30 |
// to be removed in 2.0, used name instead
|
32 |
$this->setAttribute('index', $index);
|
33 |
}
|
34 |
|
35 |
+
protected function addGetTemplate(Compiler $compiler)
|
36 |
{
|
37 |
$compiler
|
38 |
->write('$this->loadTemplate(')
|
vendor/twig/twig/lib/Twig/Node/Expression.php
CHANGED
@@ -10,12 +10,14 @@
|
|
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
|
19 |
{
|
20 |
}
|
21 |
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Node\Node;
|
14 |
+
|
15 |
/**
|
16 |
* Abstract class for all nodes that represents an expression.
|
17 |
*
|
18 |
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
*/
|
20 |
+
abstract class Twig_Node_Expression extends Node
|
21 |
{
|
22 |
}
|
23 |
|
vendor/twig/twig/lib/Twig/Node/Expression/Array.php
CHANGED
@@ -8,7 +8,12 @@
|
|
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 |
protected $index;
|
14 |
|
@@ -18,7 +23,7 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression
|
|
18 |
|
19 |
$this->index = -1;
|
20 |
foreach ($this->getKeyValuePairs() as $pair) {
|
21 |
-
if ($pair['key'] instanceof
|
22 |
$this->index = $pair['key']->getAttribute('value');
|
23 |
}
|
24 |
}
|
@@ -38,7 +43,7 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression
|
|
38 |
return $pairs;
|
39 |
}
|
40 |
|
41 |
-
public function hasElement(
|
42 |
{
|
43 |
foreach ($this->getKeyValuePairs() as $pair) {
|
44 |
// we compare the string representation of the keys
|
@@ -51,16 +56,16 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression
|
|
51 |
return false;
|
52 |
}
|
53 |
|
54 |
-
public function addElement(
|
55 |
{
|
56 |
if (null === $key) {
|
57 |
-
$key = new
|
58 |
}
|
59 |
|
60 |
array_push($this->nodes, $key, $value);
|
61 |
}
|
62 |
|
63 |
-
public function compile(
|
64 |
{
|
65 |
$compiler->raw('[');
|
66 |
$first = true;
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\AbstractExpression;
|
14 |
+
use Twig\Node\Expression\ConstantExpression;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Array extends AbstractExpression
|
17 |
{
|
18 |
protected $index;
|
19 |
|
23 |
|
24 |
$this->index = -1;
|
25 |
foreach ($this->getKeyValuePairs() as $pair) {
|
26 |
+
if ($pair['key'] instanceof ConstantExpression && ctype_digit((string) $pair['key']->getAttribute('value')) && $pair['key']->getAttribute('value') > $this->index) {
|
27 |
$this->index = $pair['key']->getAttribute('value');
|
28 |
}
|
29 |
}
|
43 |
return $pairs;
|
44 |
}
|
45 |
|
46 |
+
public function hasElement(AbstractExpression $key)
|
47 |
{
|
48 |
foreach ($this->getKeyValuePairs() as $pair) {
|
49 |
// we compare the string representation of the keys
|
56 |
return false;
|
57 |
}
|
58 |
|
59 |
+
public function addElement(AbstractExpression $value, AbstractExpression $key = null)
|
60 |
{
|
61 |
if (null === $key) {
|
62 |
+
$key = new ConstantExpression(++$this->index, $value->getTemplateLine());
|
63 |
}
|
64 |
|
65 |
array_push($this->nodes, $key, $value);
|
66 |
}
|
67 |
|
68 |
+
public function compile(Compiler $compiler)
|
69 |
{
|
70 |
$compiler->raw('[');
|
71 |
$first = true;
|
vendor/twig/twig/lib/Twig/Node/Expression/AssignName.php
CHANGED
@@ -10,9 +10,12 @@
|
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
-
|
|
|
|
|
|
|
14 |
{
|
15 |
-
public function compile(
|
16 |
{
|
17 |
$compiler
|
18 |
->raw('$context[')
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\NameExpression;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_AssignName extends NameExpression
|
17 |
{
|
18 |
+
public function compile(Compiler $compiler)
|
19 |
{
|
20 |
$compiler
|
21 |
->raw('$context[')
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary.php
CHANGED
@@ -9,14 +9,18 @@
|
|
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 |
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(
|
20 |
{
|
21 |
$compiler
|
22 |
->raw('(')
|
@@ -31,7 +35,7 @@ abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression
|
|
31 |
;
|
32 |
}
|
33 |
|
34 |
-
abstract public function operator(
|
35 |
}
|
36 |
|
37 |
class_alias('Twig_Node_Expression_Binary', 'Twig\Node\Expression\Binary\AbstractBinary', false);
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\AbstractExpression;
|
15 |
+
|
16 |
+
abstract class Twig_Node_Expression_Binary extends AbstractExpression
|
17 |
{
|
18 |
public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
|
19 |
{
|
20 |
parent::__construct(['left' => $left, 'right' => $right], [], $lineno);
|
21 |
}
|
22 |
|
23 |
+
public function compile(Compiler $compiler)
|
24 |
{
|
25 |
$compiler
|
26 |
->raw('(')
|
35 |
;
|
36 |
}
|
37 |
|
38 |
+
abstract public function operator(Compiler $compiler);
|
39 |
}
|
40 |
|
41 |
class_alias('Twig_Node_Expression_Binary', 'Twig\Node\Expression\Binary\AbstractBinary', false);
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/Add.php
CHANGED
@@ -9,9 +9,13 @@
|
|
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 |
-
public function operator(
|
15 |
{
|
16 |
return $compiler->raw('+');
|
17 |
}
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Binary_Add extends AbstractBinary
|
17 |
{
|
18 |
+
public function operator(Compiler $compiler)
|
19 |
{
|
20 |
return $compiler->raw('+');
|
21 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/And.php
CHANGED
@@ -9,9 +9,13 @@
|
|
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 |
-
public function operator(
|
15 |
{
|
16 |
return $compiler->raw('&&');
|
17 |
}
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Binary_And extends AbstractBinary
|
17 |
{
|
18 |
+
public function operator(Compiler $compiler)
|
19 |
{
|
20 |
return $compiler->raw('&&');
|
21 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php
CHANGED
@@ -9,9 +9,13 @@
|
|
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 |
-
public function operator(
|
15 |
{
|
16 |
return $compiler->raw('&');
|
17 |
}
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Binary_BitwiseAnd extends AbstractBinary
|
17 |
{
|
18 |
+
public function operator(Compiler $compiler)
|
19 |
{
|
20 |
return $compiler->raw('&');
|
21 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php
CHANGED
@@ -9,9 +9,13 @@
|
|
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 |
-
public function operator(
|
15 |
{
|
16 |
return $compiler->raw('|');
|
17 |
}
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Binary_BitwiseOr extends AbstractBinary
|
17 |
{
|
18 |
+
public function operator(Compiler $compiler)
|
19 |
{
|
20 |
return $compiler->raw('|');
|
21 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php
CHANGED
@@ -9,9 +9,13 @@
|
|
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 |
-
public function operator(
|
15 |
{
|
16 |
return $compiler->raw('^');
|
17 |
}
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Binary_BitwiseXor extends AbstractBinary
|
17 |
{
|
18 |
+
public function operator(Compiler $compiler)
|
19 |
{
|
20 |
return $compiler->raw('^');
|
21 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/Concat.php
CHANGED
@@ -9,9 +9,13 @@
|
|
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 |
-
public function operator(
|
15 |
{
|
16 |
return $compiler->raw('.');
|
17 |
}
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Binary_Concat extends AbstractBinary
|
17 |
{
|
18 |
+
public function operator(Compiler $compiler)
|
19 |
{
|
20 |
return $compiler->raw('.');
|
21 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/Div.php
CHANGED
@@ -9,9 +9,13 @@
|
|
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 |
-
public function operator(
|
15 |
{
|
16 |
return $compiler->raw('/');
|
17 |
}
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Binary_Div extends AbstractBinary
|
17 |
{
|
18 |
+
public function operator(Compiler $compiler)
|
19 |
{
|
20 |
return $compiler->raw('/');
|
21 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php
CHANGED
@@ -8,9 +8,13 @@
|
|
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 |
-
public function compile(
|
14 |
{
|
15 |
$left = $compiler->getVarName();
|
16 |
$right = $compiler->getVarName();
|
@@ -23,7 +27,7 @@ class Twig_Node_Expression_Binary_EndsWith extends Twig_Node_Expression_Binary
|
|
23 |
;
|
24 |
}
|
25 |
|
26 |
-
public function operator(
|
27 |
{
|
28 |
return $compiler->raw('');
|
29 |
}
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
14 |
+
|
15 |
+
class Twig_Node_Expression_Binary_EndsWith extends AbstractBinary
|
16 |
{
|
17 |
+
public function compile(Compiler $compiler)
|
18 |
{
|
19 |
$left = $compiler->getVarName();
|
20 |
$right = $compiler->getVarName();
|
27 |
;
|
28 |
}
|
29 |
|
30 |
+
public function operator(Compiler $compiler)
|
31 |
{
|
32 |
return $compiler->raw('');
|
33 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/Equal.php
CHANGED
@@ -8,9 +8,13 @@
|
|
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 |
-
public function operator(
|
14 |
{
|
15 |
return $compiler->raw('==');
|
16 |
}
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
14 |
+
|
15 |
+
class Twig_Node_Expression_Binary_Equal extends AbstractBinary
|
16 |
{
|
17 |
+
public function operator(Compiler $compiler)
|
18 |
{
|
19 |
return $compiler->raw('==');
|
20 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php
CHANGED
@@ -8,16 +8,20 @@
|
|
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 |
-
public function compile(
|
14 |
{
|
15 |
$compiler->raw('(int) floor(');
|
16 |
parent::compile($compiler);
|
17 |
$compiler->raw(')');
|
18 |
}
|
19 |
|
20 |
-
public function operator(
|
21 |
{
|
22 |
return $compiler->raw('/');
|
23 |
}
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
14 |
+
|
15 |
+
class Twig_Node_Expression_Binary_FloorDiv extends AbstractBinary
|
16 |
{
|
17 |
+
public function compile(Compiler $compiler)
|
18 |
{
|
19 |
$compiler->raw('(int) floor(');
|
20 |
parent::compile($compiler);
|
21 |
$compiler->raw(')');
|
22 |
}
|
23 |
|
24 |
+
public function operator(Compiler $compiler)
|
25 |
{
|
26 |
return $compiler->raw('/');
|
27 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/Greater.php
CHANGED
@@ -8,9 +8,13 @@
|
|
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 |
-
public function operator(
|
14 |
{
|
15 |
return $compiler->raw('>');
|
16 |
}
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
14 |
+
|
15 |
+
class Twig_Node_Expression_Binary_Greater extends AbstractBinary
|
16 |
{
|
17 |
+
public function operator(Compiler $compiler)
|
18 |
{
|
19 |
return $compiler->raw('>');
|
20 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php
CHANGED
@@ -8,9 +8,13 @@
|
|
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 |
-
public function operator(
|
14 |
{
|
15 |
return $compiler->raw('>=');
|
16 |
}
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
14 |
+
|
15 |
+
class Twig_Node_Expression_Binary_GreaterEqual extends AbstractBinary
|
16 |
{
|
17 |
+
public function operator(Compiler $compiler)
|
18 |
{
|
19 |
return $compiler->raw('>=');
|
20 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/In.php
CHANGED
@@ -8,9 +8,13 @@
|
|
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 |
-
public function compile(
|
14 |
{
|
15 |
$compiler
|
16 |
->raw('twig_in_filter(')
|
@@ -21,7 +25,7 @@ class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary
|
|
21 |
;
|
22 |
}
|
23 |
|
24 |
-
public function operator(
|
25 |
{
|
26 |
return $compiler->raw('in');
|
27 |
}
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
14 |
+
|
15 |
+
class Twig_Node_Expression_Binary_In extends AbstractBinary
|
16 |
{
|
17 |
+
public function compile(Compiler $compiler)
|
18 |
{
|
19 |
$compiler
|
20 |
->raw('twig_in_filter(')
|
25 |
;
|
26 |
}
|
27 |
|
28 |
+
public function operator(Compiler $compiler)
|
29 |
{
|
30 |
return $compiler->raw('in');
|
31 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/Less.php
CHANGED
@@ -8,9 +8,13 @@
|
|
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 |
-
public function operator(
|
14 |
{
|
15 |
return $compiler->raw('<');
|
16 |
}
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
14 |
+
|
15 |
+
class Twig_Node_Expression_Binary_Less extends AbstractBinary
|
16 |
{
|
17 |
+
public function operator(Compiler $compiler)
|
18 |
{
|
19 |
return $compiler->raw('<');
|
20 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/LessEqual.php
CHANGED
@@ -8,9 +8,13 @@
|
|
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 |
-
public function operator(
|
14 |
{
|
15 |
return $compiler->raw('<=');
|
16 |
}
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
14 |
+
|
15 |
+
class Twig_Node_Expression_Binary_LessEqual extends AbstractBinary
|
16 |
{
|
17 |
+
public function operator(Compiler $compiler)
|
18 |
{
|
19 |
return $compiler->raw('<=');
|
20 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php
CHANGED
@@ -8,9 +8,13 @@
|
|
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 |
-
public function compile(
|
14 |
{
|
15 |
$compiler
|
16 |
->raw('preg_match(')
|
@@ -21,7 +25,7 @@ class Twig_Node_Expression_Binary_Matches extends Twig_Node_Expression_Binary
|
|
21 |
;
|
22 |
}
|
23 |
|
24 |
-
public function operator(
|
25 |
{
|
26 |
return $compiler->raw('');
|
27 |
}
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
14 |
+
|
15 |
+
class Twig_Node_Expression_Binary_Matches extends AbstractBinary
|
16 |
{
|
17 |
+
public function compile(Compiler $compiler)
|
18 |
{
|
19 |
$compiler
|
20 |
->raw('preg_match(')
|
25 |
;
|
26 |
}
|
27 |
|
28 |
+
public function operator(Compiler $compiler)
|
29 |
{
|
30 |
return $compiler->raw('');
|
31 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mod.php
CHANGED
@@ -9,9 +9,13 @@
|
|
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 |
-
public function operator(
|
15 |
{
|
16 |
return $compiler->raw('%');
|
17 |
}
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Binary_Mod extends AbstractBinary
|
17 |
{
|
18 |
+
public function operator(Compiler $compiler)
|
19 |
{
|
20 |
return $compiler->raw('%');
|
21 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mul.php
CHANGED
@@ -9,9 +9,13 @@
|
|
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 |
-
public function operator(
|
15 |
{
|
16 |
return $compiler->raw('*');
|
17 |
}
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Binary_Mul extends AbstractBinary
|
17 |
{
|
18 |
+
public function operator(Compiler $compiler)
|
19 |
{
|
20 |
return $compiler->raw('*');
|
21 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotEqual.php
CHANGED
@@ -8,9 +8,13 @@
|
|
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 |
-
public function operator(
|
14 |
{
|
15 |
return $compiler->raw('!=');
|
16 |
}
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
14 |
+
|
15 |
+
class Twig_Node_Expression_Binary_NotEqual extends AbstractBinary
|
16 |
{
|
17 |
+
public function operator(Compiler $compiler)
|
18 |
{
|
19 |
return $compiler->raw('!=');
|
20 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php
CHANGED
@@ -8,9 +8,13 @@
|
|
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 |
-
public function compile(
|
14 |
{
|
15 |
$compiler
|
16 |
->raw('!twig_in_filter(')
|
@@ -21,7 +25,7 @@ class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary
|
|
21 |
;
|
22 |
}
|
23 |
|
24 |
-
public function operator(
|
25 |
{
|
26 |
return $compiler->raw('not in');
|
27 |
}
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
14 |
+
|
15 |
+
class Twig_Node_Expression_Binary_NotIn extends AbstractBinary
|
16 |
{
|
17 |
+
public function compile(Compiler $compiler)
|
18 |
{
|
19 |
$compiler
|
20 |
->raw('!twig_in_filter(')
|
25 |
;
|
26 |
}
|
27 |
|
28 |
+
public function operator(Compiler $compiler)
|
29 |
{
|
30 |
return $compiler->raw('not in');
|
31 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/Or.php
CHANGED
@@ -9,9 +9,13 @@
|
|
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 |
-
public function operator(
|
15 |
{
|
16 |
return $compiler->raw('||');
|
17 |
}
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Binary_Or extends AbstractBinary
|
17 |
{
|
18 |
+
public function operator(Compiler $compiler)
|
19 |
{
|
20 |
return $compiler->raw('||');
|
21 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/Power.php
CHANGED
@@ -8,9 +8,13 @@
|
|
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 |
-
public function compile(
|
14 |
{
|
15 |
if (PHP_VERSION_ID >= 50600) {
|
16 |
return parent::compile($compiler);
|
@@ -25,7 +29,7 @@ class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary
|
|
25 |
;
|
26 |
}
|
27 |
|
28 |
-
public function operator(
|
29 |
{
|
30 |
return $compiler->raw('**');
|
31 |
}
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
14 |
+
|
15 |
+
class Twig_Node_Expression_Binary_Power extends AbstractBinary
|
16 |
{
|
17 |
+
public function compile(Compiler $compiler)
|
18 |
{
|
19 |
if (PHP_VERSION_ID >= 50600) {
|
20 |
return parent::compile($compiler);
|
29 |
;
|
30 |
}
|
31 |
|
32 |
+
public function operator(Compiler $compiler)
|
33 |
{
|
34 |
return $compiler->raw('**');
|
35 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/Range.php
CHANGED
@@ -8,9 +8,13 @@
|
|
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 |
-
public function compile(
|
14 |
{
|
15 |
$compiler
|
16 |
->raw('range(')
|
@@ -21,7 +25,7 @@ class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary
|
|
21 |
;
|
22 |
}
|
23 |
|
24 |
-
public function operator(
|
25 |
{
|
26 |
return $compiler->raw('..');
|
27 |
}
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
14 |
+
|
15 |
+
class Twig_Node_Expression_Binary_Range extends AbstractBinary
|
16 |
{
|
17 |
+
public function compile(Compiler $compiler)
|
18 |
{
|
19 |
$compiler
|
20 |
->raw('range(')
|
25 |
;
|
26 |
}
|
27 |
|
28 |
+
public function operator(Compiler $compiler)
|
29 |
{
|
30 |
return $compiler->raw('..');
|
31 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php
CHANGED
@@ -8,9 +8,13 @@
|
|
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 |
-
public function compile(
|
14 |
{
|
15 |
$left = $compiler->getVarName();
|
16 |
$right = $compiler->getVarName();
|
@@ -23,7 +27,7 @@ class Twig_Node_Expression_Binary_StartsWith extends Twig_Node_Expression_Binary
|
|
23 |
;
|
24 |
}
|
25 |
|
26 |
-
public function operator(
|
27 |
{
|
28 |
return $compiler->raw('');
|
29 |
}
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
14 |
+
|
15 |
+
class Twig_Node_Expression_Binary_StartsWith extends AbstractBinary
|
16 |
{
|
17 |
+
public function compile(Compiler $compiler)
|
18 |
{
|
19 |
$left = $compiler->getVarName();
|
20 |
$right = $compiler->getVarName();
|
27 |
;
|
28 |
}
|
29 |
|
30 |
+
public function operator(Compiler $compiler)
|
31 |
{
|
32 |
return $compiler->raw('');
|
33 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Binary/Sub.php
CHANGED
@@ -9,9 +9,13 @@
|
|
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 |
-
public function operator(
|
15 |
{
|
16 |
return $compiler->raw('-');
|
17 |
}
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\Binary\AbstractBinary;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Binary_Sub extends AbstractBinary
|
17 |
{
|
18 |
+
public function operator(Compiler $compiler)
|
19 |
{
|
20 |
return $compiler->raw('-');
|
21 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.php
CHANGED
@@ -10,19 +10,23 @@
|
|
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
|
19 |
{
|
20 |
/**
|
21 |
-
* @param
|
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;
|
@@ -36,7 +40,7 @@ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
|
|
36 |
parent::__construct($nodes, ['is_defined_test' => false, 'output' => false], $lineno, $tag);
|
37 |
}
|
38 |
|
39 |
-
public function compile(
|
40 |
{
|
41 |
if ($this->getAttribute('is_defined_test')) {
|
42 |
$this->compileTemplateCall($compiler, 'hasBlock');
|
@@ -53,7 +57,7 @@ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
|
|
53 |
}
|
54 |
}
|
55 |
|
56 |
-
private function compileTemplateCall(
|
57 |
{
|
58 |
if (!$this->hasNode('template')) {
|
59 |
$compiler->write('$this');
|
@@ -75,7 +79,7 @@ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
|
|
75 |
return $compiler;
|
76 |
}
|
77 |
|
78 |
-
private function compileBlockArguments(
|
79 |
{
|
80 |
$compiler
|
81 |
->raw('(')
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\AbstractExpression;
|
15 |
+
use Twig\Node\Node;
|
16 |
+
|
17 |
/**
|
18 |
* Represents a block call node.
|
19 |
*
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
+
class Twig_Node_Expression_BlockReference extends AbstractExpression
|
23 |
{
|
24 |
/**
|
25 |
+
* @param Node|null $template
|
26 |
*/
|
27 |
public function __construct(Twig_NodeInterface $name, $template = null, $lineno, $tag = null)
|
28 |
{
|
29 |
+
if (\is_bool($template)) {
|
30 |
@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);
|
31 |
|
32 |
$template = null;
|
40 |
parent::__construct($nodes, ['is_defined_test' => false, 'output' => false], $lineno, $tag);
|
41 |
}
|
42 |
|
43 |
+
public function compile(Compiler $compiler)
|
44 |
{
|
45 |
if ($this->getAttribute('is_defined_test')) {
|
46 |
$this->compileTemplateCall($compiler, 'hasBlock');
|
57 |
}
|
58 |
}
|
59 |
|
60 |
+
private function compileTemplateCall(Compiler $compiler, $method)
|
61 |
{
|
62 |
if (!$this->hasNode('template')) {
|
63 |
$compiler->write('$this');
|
79 |
return $compiler;
|
80 |
}
|
81 |
|
82 |
+
private function compileBlockArguments(Compiler $compiler)
|
83 |
{
|
84 |
$compiler
|
85 |
->raw('(')
|
vendor/twig/twig/lib/Twig/Node/Expression/Call.php
CHANGED
@@ -8,27 +8,36 @@
|
|
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 |
private $reflector;
|
14 |
|
15 |
-
protected function compileCallable(
|
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
|
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')));
|
@@ -47,7 +56,7 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
47 |
}
|
48 |
}
|
49 |
|
50 |
-
protected function compileArguments(
|
51 |
{
|
52 |
$compiler->raw($isArray ? '[' : '(');
|
53 |
|
@@ -109,11 +118,11 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
109 |
$parameters = [];
|
110 |
$named = false;
|
111 |
foreach ($arguments as $name => $node) {
|
112 |
-
if (
|
113 |
$named = true;
|
114 |
$name = $this->normalizeName($name);
|
115 |
} elseif ($named) {
|
116 |
-
throw new
|
117 |
}
|
118 |
|
119 |
$parameters[$name] = $node;
|
@@ -131,7 +140,7 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
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);
|
@@ -143,15 +152,15 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
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
|
149 |
}
|
150 |
|
151 |
-
if (count($missingArguments)) {
|
152 |
-
throw new
|
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 |
|
@@ -159,14 +168,14 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
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
|
170 |
} elseif ($callableParameter->isOptional()) {
|
171 |
if (empty($parameters)) {
|
172 |
break;
|
@@ -174,17 +183,17 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
174 |
$missingArguments[] = $name;
|
175 |
}
|
176 |
} else {
|
177 |
-
throw new
|
178 |
}
|
179 |
}
|
180 |
|
181 |
if ($isVariadic) {
|
182 |
-
$arbitraryArguments = new
|
183 |
foreach ($parameters as $key => $value) {
|
184 |
-
if (is_int($key)) {
|
185 |
$arbitraryArguments->addElement($value);
|
186 |
} else {
|
187 |
-
$arbitraryArguments->addElement($value, new
|
188 |
}
|
189 |
unset($parameters[$key]);
|
190 |
}
|
@@ -198,15 +207,15 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
198 |
if (!empty($parameters)) {
|
199 |
$unknownParameter = null;
|
200 |
foreach ($parameters as $parameter) {
|
201 |
-
if ($parameter instanceof
|
202 |
$unknownParameter = $parameter;
|
203 |
break;
|
204 |
}
|
205 |
}
|
206 |
|
207 |
-
throw new
|
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 |
|
@@ -246,11 +255,11 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
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 |
|
@@ -263,27 +272,27 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|
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];
|
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 Twig\Compiler;
|
13 |
+
use Twig\Error\SyntaxError;
|
14 |
+
use Twig\Extension\ExtensionInterface;
|
15 |
+
use Twig\Node\Expression\AbstractExpression;
|
16 |
+
use Twig\Node\Expression\ArrayExpression;
|
17 |
+
use Twig\Node\Expression\ConstantExpression;
|
18 |
+
use Twig\Node\Node;
|
19 |
+
|
20 |
+
abstract class Twig_Node_Expression_Call extends AbstractExpression
|
21 |
{
|
22 |
private $reflector;
|
23 |
|
24 |
+
protected function compileCallable(Compiler $compiler)
|
25 |
{
|
26 |
$closingParenthesis = false;
|
27 |
$isArray = false;
|
28 |
if ($this->hasAttribute('callable') && $callable = $this->getAttribute('callable')) {
|
29 |
+
if (\is_string($callable) && false === strpos($callable, '::')) {
|
30 |
$compiler->raw($callable);
|
31 |
} else {
|
32 |
list($r, $callable) = $this->reflectCallable($callable);
|
33 |
+
if ($r instanceof \ReflectionMethod && \is_string($callable[0])) {
|
34 |
if ($r->isStatic()) {
|
35 |
$compiler->raw(sprintf('%s::%s', $callable[0], $callable[1]));
|
36 |
} else {
|
37 |
$compiler->raw(sprintf('$this->env->getRuntime(\'%s\')->%s', $callable[0], $callable[1]));
|
38 |
}
|
39 |
+
} elseif ($r instanceof \ReflectionMethod && $callable[0] instanceof ExtensionInterface) {
|
40 |
+
$compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', \get_class($callable[0]), $callable[1]));
|
41 |
} else {
|
42 |
$type = ucfirst($this->getAttribute('type'));
|
43 |
$compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), ', $type, $this->getAttribute('name')));
|
56 |
}
|
57 |
}
|
58 |
|
59 |
+
protected function compileArguments(Compiler $compiler, $isArray = false)
|
60 |
{
|
61 |
$compiler->raw($isArray ? '[' : '(');
|
62 |
|
118 |
$parameters = [];
|
119 |
$named = false;
|
120 |
foreach ($arguments as $name => $node) {
|
121 |
+
if (!\is_int($name)) {
|
122 |
$named = true;
|
123 |
$name = $this->normalizeName($name);
|
124 |
} elseif ($named) {
|
125 |
+
throw new SyntaxError(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName), $this->getTemplateLine());
|
126 |
}
|
127 |
|
128 |
$parameters[$name] = $node;
|
140 |
$message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName);
|
141 |
}
|
142 |
|
143 |
+
throw new \LogicException($message);
|
144 |
}
|
145 |
|
146 |
$callableParameters = $this->getCallableParameters($callable, $isVariadic);
|
152 |
foreach ($callableParameters as $callableParameter) {
|
153 |
$names[] = $name = $this->normalizeName($callableParameter->name);
|
154 |
|
155 |
+
if (\array_key_exists($name, $parameters)) {
|
156 |
+
if (\array_key_exists($pos, $parameters)) {
|
157 |
+
throw new SyntaxError(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName), $this->getTemplateLine());
|
158 |
}
|
159 |
|
160 |
+
if (\count($missingArguments)) {
|
161 |
+
throw new SyntaxError(sprintf(
|
162 |
'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".',
|
163 |
+
$name, $callType, $callName, implode(', ', $names), \count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments)
|
164 |
), $this->getTemplateLine());
|
165 |
}
|
166 |
|
168 |
$arguments[] = $parameters[$name];
|
169 |
unset($parameters[$name]);
|
170 |
$optionalArguments = [];
|
171 |
+
} elseif (\array_key_exists($pos, $parameters)) {
|
172 |
$arguments = array_merge($arguments, $optionalArguments);
|
173 |
$arguments[] = $parameters[$pos];
|
174 |
unset($parameters[$pos]);
|
175 |
$optionalArguments = [];
|
176 |
++$pos;
|
177 |
} elseif ($callableParameter->isDefaultValueAvailable()) {
|
178 |
+
$optionalArguments[] = new ConstantExpression($callableParameter->getDefaultValue(), -1);
|
179 |
} elseif ($callableParameter->isOptional()) {
|
180 |
if (empty($parameters)) {
|
181 |
break;
|
183 |
$missingArguments[] = $name;
|
184 |
}
|
185 |
} else {
|
186 |
+
throw new SyntaxError(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName), $this->getTemplateLine());
|
187 |
}
|
188 |
}
|
189 |
|
190 |
if ($isVariadic) {
|
191 |
+
$arbitraryArguments = new ArrayExpression([], -1);
|
192 |
foreach ($parameters as $key => $value) {
|
193 |
+
if (\is_int($key)) {
|
194 |
$arbitraryArguments->addElement($value);
|
195 |
} else {
|
196 |
+
$arbitraryArguments->addElement($value, new ConstantExpression($key, -1));
|
197 |
}
|
198 |
unset($parameters[$key]);
|
199 |
}
|
207 |
if (!empty($parameters)) {
|
208 |
$unknownParameter = null;
|
209 |
foreach ($parameters as $parameter) {
|
210 |
+
if ($parameter instanceof Node) {
|
211 |
$unknownParameter = $parameter;
|
212 |
break;
|
213 |
}
|
214 |
}
|
215 |
|
216 |
+
throw new SyntaxError(sprintf(
|
217 |
'Unknown argument%s "%s" for %s "%s(%s)".',
|
218 |
+
\count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names)
|
219 |
), $unknownParameter ? $unknownParameter->getTemplateLine() : $this->getTemplateLine());
|
220 |
}
|
221 |
|
255 |
array_pop($parameters);
|
256 |
} else {
|
257 |
$callableName = $r->name;
|
258 |
+
if ($r instanceof \ReflectionMethod) {
|
259 |
$callableName = $r->getDeclaringClass()->name.'::'.$callableName;
|
260 |
}
|
261 |
|
262 |
+
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')));
|
263 |
}
|
264 |
}
|
265 |
|
272 |
return $this->reflector;
|
273 |
}
|
274 |
|
275 |
+
if (\is_array($callable)) {
|
276 |
if (!method_exists($callable[0], $callable[1])) {
|
277 |
// __call()
|
278 |
return [null, []];
|
279 |
}
|
280 |
+
$r = new \ReflectionMethod($callable[0], $callable[1]);
|
281 |
+
} elseif (\is_object($callable) && !$callable instanceof Closure) {
|
282 |
+
$r = new \ReflectionObject($callable);
|
283 |
$r = $r->getMethod('__invoke');
|
284 |
$callable = [$callable, '__invoke'];
|
285 |
+
} elseif (\is_string($callable) && false !== $pos = strpos($callable, '::')) {
|
286 |
$class = substr($callable, 0, $pos);
|
287 |
$method = substr($callable, $pos + 2);
|
288 |
if (!method_exists($class, $method)) {
|
289 |
// __staticCall()
|
290 |
return [null, []];
|
291 |
}
|
292 |
+
$r = new \ReflectionMethod($callable);
|
293 |
$callable = [$class, $method];
|
294 |
} else {
|
295 |
+
$r = new \ReflectionFunction($callable);
|
296 |
}
|
297 |
|
298 |
return $this->reflector = [$r, $callable];
|
vendor/twig/twig/lib/Twig/Node/Expression/Conditional.php
CHANGED
@@ -9,14 +9,18 @@
|
|
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 |
-
public function __construct(
|
15 |
{
|
16 |
parent::__construct(['expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3], [], $lineno);
|
17 |
}
|
18 |
|
19 |
-
public function compile(
|
20 |
{
|
21 |
$compiler
|
22 |
->raw('((')
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\AbstractExpression;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Conditional extends AbstractExpression
|
17 |
{
|
18 |
+
public function __construct(AbstractExpression $expr1, AbstractExpression $expr2, AbstractExpression $expr3, $lineno)
|
19 |
{
|
20 |
parent::__construct(['expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3], [], $lineno);
|
21 |
}
|
22 |
|
23 |
+
public function compile(Compiler $compiler)
|
24 |
{
|
25 |
$compiler
|
26 |
->raw('((')
|
vendor/twig/twig/lib/Twig/Node/Expression/Constant.php
CHANGED
@@ -9,14 +9,18 @@
|
|
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 |
public function __construct($value, $lineno)
|
15 |
{
|
16 |
parent::__construct([], ['value' => $value], $lineno);
|
17 |
}
|
18 |
|
19 |
-
public function compile(
|
20 |
{
|
21 |
$compiler->repr($this->getAttribute('value'));
|
22 |
}
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\AbstractExpression;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Constant extends AbstractExpression
|
17 |
{
|
18 |
public function __construct($value, $lineno)
|
19 |
{
|
20 |
parent::__construct([], ['value' => $value], $lineno);
|
21 |
}
|
22 |
|
23 |
+
public function compile(Compiler $compiler)
|
24 |
{
|
25 |
$compiler->repr($this->getAttribute('value'));
|
26 |
}
|
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
|
22 |
{
|
23 |
public function __construct($name, $lineno, $tag = null)
|
24 |
{
|
25 |
parent::__construct([], ['name' => $name], $lineno, $tag);
|
26 |
}
|
27 |
|
28 |
-
public function compile(
|
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 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Filter.php
CHANGED
@@ -9,14 +9,20 @@
|
|
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 |
-
public function __construct(Twig_NodeInterface $node,
|
15 |
{
|
16 |
parent::__construct(['node' => $node, 'filter' => $filterName, 'arguments' => $arguments], [], $lineno, $tag);
|
17 |
}
|
18 |
|
19 |
-
public function compile(
|
20 |
{
|
21 |
$name = $this->getNode('filter')->getAttribute('value');
|
22 |
$filter = $compiler->getEnvironment()->getFilter($name);
|
@@ -27,10 +33,10 @@ class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call
|
|
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
|
31 |
$this->setAttribute('callable', $filter->getCallable());
|
32 |
}
|
33 |
-
if ($filter instanceof
|
34 |
$this->setAttribute('is_variadic', $filter->isVariadic());
|
35 |
}
|
36 |
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\CallExpression;
|
15 |
+
use Twig\Node\Expression\ConstantExpression;
|
16 |
+
use Twig\TwigFilter;
|
17 |
+
|
18 |
+
class Twig_Node_Expression_Filter extends CallExpression
|
19 |
{
|
20 |
+
public function __construct(Twig_NodeInterface $node, ConstantExpression $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
|
21 |
{
|
22 |
parent::__construct(['node' => $node, 'filter' => $filterName, 'arguments' => $arguments], [], $lineno, $tag);
|
23 |
}
|
24 |
|
25 |
+
public function compile(Compiler $compiler)
|
26 |
{
|
27 |
$name = $this->getNode('filter')->getAttribute('value');
|
28 |
$filter = $compiler->getEnvironment()->getFilter($name);
|
33 |
$this->setAttribute('needs_environment', $filter->needsEnvironment());
|
34 |
$this->setAttribute('needs_context', $filter->needsContext());
|
35 |
$this->setAttribute('arguments', $filter->getArguments());
|
36 |
+
if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof TwigFilter) {
|
37 |
$this->setAttribute('callable', $filter->getCallable());
|
38 |
}
|
39 |
+
if ($filter instanceof TwigFilter) {
|
40 |
$this->setAttribute('is_variadic', $filter->isVariadic());
|
41 |
}
|
42 |
|
vendor/twig/twig/lib/Twig/Node/Expression/Filter/Default.php
CHANGED
@@ -9,26 +9,33 @@
|
|
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
|
22 |
{
|
23 |
-
public function __construct(Twig_NodeInterface $node,
|
24 |
{
|
25 |
-
$default = new
|
26 |
|
27 |
-
if ('default' === $filterName->getAttribute('value') && ($node instanceof
|
28 |
-
$test = new
|
29 |
-
$false = count($arguments) ? $arguments->getNode(0) : new
|
30 |
|
31 |
-
$node = new
|
32 |
} else {
|
33 |
$node = $default;
|
34 |
}
|
@@ -36,7 +43,7 @@ class Twig_Node_Expression_Filter_Default extends Twig_Node_Expression_Filter
|
|
36 |
parent::__construct($node, $filterName, $arguments, $lineno, $tag);
|
37 |
}
|
38 |
|
39 |
-
public function compile(
|
40 |
{
|
41 |
$compiler->subcompile($this->getNode('node'));
|
42 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\ConditionalExpression;
|
14 |
+
use Twig\Node\Expression\ConstantExpression;
|
15 |
+
use Twig\Node\Expression\FilterExpression;
|
16 |
+
use Twig\Node\Expression\GetAttrExpression;
|
17 |
+
use Twig\Node\Expression\NameExpression;
|
18 |
+
use Twig\Node\Expression\Test\DefinedTest;
|
19 |
+
use Twig\Node\Node;
|
20 |
+
|
21 |
/**
|
22 |
* Returns the value or the default value when it is undefined or empty.
|
23 |
*
|
|
|
24 |
* {{ var.foo|default('foo item on var is not defined') }}
|
|
|
25 |
*
|
26 |
* @author Fabien Potencier <fabien@symfony.com>
|
27 |
*/
|
28 |
+
class Twig_Node_Expression_Filter_Default extends FilterExpression
|
29 |
{
|
30 |
+
public function __construct(Twig_NodeInterface $node, ConstantExpression $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
|
31 |
{
|
32 |
+
$default = new FilterExpression($node, new ConstantExpression('default', $node->getTemplateLine()), $arguments, $node->getTemplateLine());
|
33 |
|
34 |
+
if ('default' === $filterName->getAttribute('value') && ($node instanceof NameExpression || $node instanceof GetAttrExpression)) {
|
35 |
+
$test = new DefinedTest(clone $node, 'defined', new Node(), $node->getTemplateLine());
|
36 |
+
$false = \count($arguments) ? $arguments->getNode(0) : new ConstantExpression('', $node->getTemplateLine());
|
37 |
|
38 |
+
$node = new ConditionalExpression($test, $default, $false, $node->getTemplateLine());
|
39 |
} else {
|
40 |
$node = $default;
|
41 |
}
|
43 |
parent::__construct($node, $filterName, $arguments, $lineno, $tag);
|
44 |
}
|
45 |
|
46 |
+
public function compile(Compiler $compiler)
|
47 |
{
|
48 |
$compiler->subcompile($this->getNode('node'));
|
49 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Function.php
CHANGED
@@ -8,14 +8,19 @@
|
|
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 |
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(
|
19 |
{
|
20 |
$name = $this->getAttribute('name');
|
21 |
$function = $compiler->getEnvironment()->getFunction($name);
|
@@ -26,7 +31,7 @@ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
|
|
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
|
30 |
$callable = $function->getCallable();
|
31 |
if ('constant' === $name && $this->getAttribute('is_defined_test')) {
|
32 |
$callable = 'twig_constant_is_defined';
|
@@ -34,7 +39,7 @@ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
|
|
34 |
|
35 |
$this->setAttribute('callable', $callable);
|
36 |
}
|
37 |
-
if ($function instanceof
|
38 |
$this->setAttribute('is_variadic', $function->isVariadic());
|
39 |
}
|
40 |
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\CallExpression;
|
14 |
+
use Twig\TwigFunction;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Function extends CallExpression
|
17 |
{
|
18 |
public function __construct($name, Twig_NodeInterface $arguments, $lineno)
|
19 |
{
|
20 |
parent::__construct(['arguments' => $arguments], ['name' => $name, 'is_defined_test' => false], $lineno);
|
21 |
}
|
22 |
|
23 |
+
public function compile(Compiler $compiler)
|
24 |
{
|
25 |
$name = $this->getAttribute('name');
|
26 |
$function = $compiler->getEnvironment()->getFunction($name);
|
31 |
$this->setAttribute('needs_environment', $function->needsEnvironment());
|
32 |
$this->setAttribute('needs_context', $function->needsContext());
|
33 |
$this->setAttribute('arguments', $function->getArguments());
|
34 |
+
if ($function instanceof Twig_FunctionCallableInterface || $function instanceof TwigFunction) {
|
35 |
$callable = $function->getCallable();
|
36 |
if ('constant' === $name && $this->getAttribute('is_defined_test')) {
|
37 |
$callable = 'twig_constant_is_defined';
|
39 |
|
40 |
$this->setAttribute('callable', $callable);
|
41 |
}
|
42 |
+
if ($function instanceof TwigFunction) {
|
43 |
$this->setAttribute('is_variadic', $function->isVariadic());
|
44 |
}
|
45 |
|
vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php
CHANGED
@@ -9,9 +9,14 @@
|
|
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 |
-
public function __construct(
|
15 |
{
|
16 |
$nodes = ['node' => $node, 'attribute' => $attribute];
|
17 |
if (null !== $arguments) {
|
@@ -21,13 +26,13 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
|
|
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(
|
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(');
|
@@ -44,7 +49,7 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
|
|
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 ||
|
48 |
$needFirst = $needSecond || $this->hasNode('arguments');
|
49 |
|
50 |
if ($needFirst) {
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\AbstractExpression;
|
15 |
+
use Twig\Template;
|
16 |
+
|
17 |
+
class Twig_Node_Expression_GetAttr extends AbstractExpression
|
18 |
{
|
19 |
+
public function __construct(AbstractExpression $node, AbstractExpression $attribute, AbstractExpression $arguments = null, $type, $lineno)
|
20 |
{
|
21 |
$nodes = ['node' => $node, 'attribute' => $attribute];
|
22 |
if (null !== $arguments) {
|
26 |
parent::__construct($nodes, ['type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false], $lineno);
|
27 |
}
|
28 |
|
29 |
+
public function compile(Compiler $compiler)
|
30 |
{
|
31 |
if ($this->getAttribute('disable_c_ext')) {
|
32 |
@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);
|
33 |
}
|
34 |
|
35 |
+
if (\function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) {
|
36 |
$compiler->raw('twig_template_get_attributes($this, ');
|
37 |
} else {
|
38 |
$compiler->raw('$this->getAttribute(');
|
49 |
// only generate optional arguments when needed (to make generated code more readable)
|
50 |
$needFourth = $this->getAttribute('ignore_strict_check');
|
51 |
$needThird = $needFourth || $this->getAttribute('is_defined_test');
|
52 |
+
$needSecond = $needThird || Template::ANY_CALL !== $this->getAttribute('type');
|
53 |
$needFirst = $needSecond || $this->hasNode('arguments');
|
54 |
|
55 |
if ($needFirst) {
|
vendor/twig/twig/lib/Twig/Node/Expression/MethodCall.php
CHANGED
@@ -8,18 +8,24 @@
|
|
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 |
-
public function __construct(
|
14 |
{
|
15 |
parent::__construct(['node' => $node, 'arguments' => $arguments], ['method' => $method, 'safe' => false], $lineno);
|
16 |
|
17 |
-
if ($node instanceof
|
18 |
$node->setAttribute('always_defined', true);
|
19 |
}
|
20 |
}
|
21 |
|
22 |
-
public function compile(
|
23 |
{
|
24 |
$compiler
|
25 |
->subcompile($this->getNode('node'))
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\AbstractExpression;
|
14 |
+
use Twig\Node\Expression\ArrayExpression;
|
15 |
+
use Twig\Node\Expression\NameExpression;
|
16 |
+
|
17 |
+
class Twig_Node_Expression_MethodCall extends AbstractExpression
|
18 |
{
|
19 |
+
public function __construct(AbstractExpression $node, $method, ArrayExpression $arguments, $lineno)
|
20 |
{
|
21 |
parent::__construct(['node' => $node, 'arguments' => $arguments], ['method' => $method, 'safe' => false], $lineno);
|
22 |
|
23 |
+
if ($node instanceof NameExpression) {
|
24 |
$node->setAttribute('always_defined', true);
|
25 |
}
|
26 |
}
|
27 |
|
28 |
+
public function compile(Compiler $compiler)
|
29 |
{
|
30 |
$compiler
|
31 |
->subcompile($this->getNode('node'))
|
vendor/twig/twig/lib/Twig/Node/Expression/Name.php
CHANGED
@@ -9,7 +9,11 @@
|
|
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 |
protected $specialVars = [
|
15 |
'_self' => '$this',
|
@@ -22,7 +26,7 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression
|
|
22 |
parent::__construct([], ['name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false], $lineno);
|
23 |
}
|
24 |
|
25 |
-
public function compile(
|
26 |
{
|
27 |
$name = $this->getAttribute('name');
|
28 |
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\AbstractExpression;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Name extends AbstractExpression
|
17 |
{
|
18 |
protected $specialVars = [
|
19 |
'_self' => '$this',
|
26 |
parent::__construct([], ['name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false], $lineno);
|
27 |
}
|
28 |
|
29 |
+
public function compile(Compiler $compiler)
|
30 |
{
|
31 |
$name = $this->getAttribute('name');
|
32 |
|
vendor/twig/twig/lib/Twig/Node/Expression/NullCoalesce.php
CHANGED
@@ -8,20 +8,30 @@
|
|
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 |
public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
|
14 |
{
|
15 |
-
$test = new
|
16 |
-
new
|
17 |
-
new
|
18 |
$left->getTemplateLine()
|
19 |
);
|
20 |
|
21 |
parent::__construct($test, $left, $right, $lineno);
|
22 |
}
|
23 |
|
24 |
-
public function compile(
|
25 |
{
|
26 |
/*
|
27 |
* This optimizes only one case. PHP 7 also supports more complex expressions
|
@@ -30,7 +40,7 @@ class Twig_Node_Expression_NullCoalesce extends Twig_Node_Expression_Conditional
|
|
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
|
34 |
$this->getNode('expr2')->setAttribute('always_defined', true);
|
35 |
$compiler
|
36 |
->raw('((')
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\Binary\AndBinary;
|
14 |
+
use Twig\Node\Expression\ConditionalExpression;
|
15 |
+
use Twig\Node\Expression\NameExpression;
|
16 |
+
use Twig\Node\Expression\Test\DefinedTest;
|
17 |
+
use Twig\Node\Expression\Test\NullTest;
|
18 |
+
use Twig\Node\Expression\Unary\NotUnary;
|
19 |
+
use Twig\Node\Node;
|
20 |
+
|
21 |
+
class Twig_Node_Expression_NullCoalesce extends ConditionalExpression
|
22 |
{
|
23 |
public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno)
|
24 |
{
|
25 |
+
$test = new AndBinary(
|
26 |
+
new DefinedTest(clone $left, 'defined', new Node(), $left->getTemplateLine()),
|
27 |
+
new NotUnary(new NullTest($left, 'null', new Node(), $left->getTemplateLine()), $left->getTemplateLine()),
|
28 |
$left->getTemplateLine()
|
29 |
);
|
30 |
|
31 |
parent::__construct($test, $left, $right, $lineno);
|
32 |
}
|
33 |
|
34 |
+
public function compile(Compiler $compiler)
|
35 |
{
|
36 |
/*
|
37 |
* This optimizes only one case. PHP 7 also supports more complex expressions
|
40 |
* cases might be implemented as an optimizer node visitor, but has not been done
|
41 |
* as benefits are probably not worth the added complexity.
|
42 |
*/
|
43 |
+
if (PHP_VERSION_ID >= 70000 && $this->getNode('expr2') instanceof NameExpression) {
|
44 |
$this->getNode('expr2')->setAttribute('always_defined', true);
|
45 |
$compiler
|
46 |
->raw('((')
|
vendor/twig/twig/lib/Twig/Node/Expression/Parent.php
CHANGED
@@ -10,19 +10,22 @@
|
|
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
|
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(
|
26 |
{
|
27 |
if ($this->getAttribute('output')) {
|
28 |
$compiler
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\AbstractExpression;
|
15 |
+
|
16 |
/**
|
17 |
* Represents a parent node.
|
18 |
*
|
19 |
* @author Fabien Potencier <fabien@symfony.com>
|
20 |
*/
|
21 |
+
class Twig_Node_Expression_Parent extends AbstractExpression
|
22 |
{
|
23 |
public function __construct($name, $lineno, $tag = null)
|
24 |
{
|
25 |
parent::__construct([], ['output' => false, 'name' => $name], $lineno, $tag);
|
26 |
}
|
27 |
|
28 |
+
public function compile(Compiler $compiler)
|
29 |
{
|
30 |
if ($this->getAttribute('output')) {
|
31 |
$compiler
|
vendor/twig/twig/lib/Twig/Node/Expression/TempName.php
CHANGED
@@ -8,14 +8,18 @@
|
|
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 |
public function __construct($name, $lineno)
|
14 |
{
|
15 |
parent::__construct([], ['name' => $name], $lineno);
|
16 |
}
|
17 |
|
18 |
-
public function compile(
|
19 |
{
|
20 |
$compiler
|
21 |
->raw('$_')
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\AbstractExpression;
|
14 |
+
|
15 |
+
class Twig_Node_Expression_TempName extends AbstractExpression
|
16 |
{
|
17 |
public function __construct($name, $lineno)
|
18 |
{
|
19 |
parent::__construct([], ['name' => $name], $lineno);
|
20 |
}
|
21 |
|
22 |
+
public function compile(Compiler $compiler)
|
23 |
{
|
24 |
$compiler
|
25 |
->raw('$_')
|
vendor/twig/twig/lib/Twig/Node/Expression/Test.php
CHANGED
@@ -8,7 +8,12 @@
|
|
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 |
public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
|
14 |
{
|
@@ -20,7 +25,7 @@ class Twig_Node_Expression_Test extends Twig_Node_Expression_Call
|
|
20 |
parent::__construct($nodes, ['name' => $name], $lineno);
|
21 |
}
|
22 |
|
23 |
-
public function compile(
|
24 |
{
|
25 |
$name = $this->getAttribute('name');
|
26 |
$test = $compiler->getEnvironment()->getTest($name);
|
@@ -28,13 +33,13 @@ class Twig_Node_Expression_Test extends Twig_Node_Expression_Call
|
|
28 |
$this->setAttribute('name', $name);
|
29 |
$this->setAttribute('type', 'test');
|
30 |
$this->setAttribute('thing', $test);
|
31 |
-
if ($test instanceof
|
32 |
$this->setAttribute('arguments', $test->getArguments());
|
33 |
}
|
34 |
-
if ($test instanceof Twig_TestCallableInterface || $test instanceof
|
35 |
$this->setAttribute('callable', $test->getCallable());
|
36 |
}
|
37 |
-
if ($test instanceof
|
38 |
$this->setAttribute('is_variadic', $test->isVariadic());
|
39 |
}
|
40 |
|
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 Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\CallExpression;
|
14 |
+
use Twig\TwigTest;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Test extends CallExpression
|
17 |
{
|
18 |
public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
|
19 |
{
|
25 |
parent::__construct($nodes, ['name' => $name], $lineno);
|
26 |
}
|
27 |
|
28 |
+
public function compile(Compiler $compiler)
|
29 |
{
|
30 |
$name = $this->getAttribute('name');
|
31 |
$test = $compiler->getEnvironment()->getTest($name);
|
33 |
$this->setAttribute('name', $name);
|
34 |
$this->setAttribute('type', 'test');
|
35 |
$this->setAttribute('thing', $test);
|
36 |
+
if ($test instanceof TwigTest) {
|
37 |
$this->setAttribute('arguments', $test->getArguments());
|
38 |
}
|
39 |
+
if ($test instanceof Twig_TestCallableInterface || $test instanceof TwigTest) {
|
40 |
$this->setAttribute('callable', $test->getCallable());
|
41 |
}
|
42 |
+
if ($test instanceof TwigTest) {
|
43 |
$this->setAttribute('is_variadic', $test->isVariadic());
|
44 |
}
|
45 |
|
vendor/twig/twig/lib/Twig/Node/Expression/Test/Constant.php
CHANGED
@@ -9,20 +9,21 @@
|
|
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 |
-
*
|
16 |
-
*
|
17 |
-
*
|
18 |
-
* {% endif %}
|
19 |
-
* </pre>
|
20 |
*
|
21 |
* @author Fabien Potencier <fabien@symfony.com>
|
22 |
*/
|
23 |
-
class Twig_Node_Expression_Test_Constant extends
|
24 |
{
|
25 |
-
public function compile(
|
26 |
{
|
27 |
$compiler
|
28 |
->raw('(')
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\TestExpression;
|
14 |
+
|
15 |
/**
|
16 |
* Checks if a variable is the exact same value as a constant.
|
17 |
*
|
18 |
+
* {% if post.status is constant('Post::PUBLISHED') %}
|
19 |
+
* the status attribute is exactly the same as Post::PUBLISHED
|
20 |
+
* {% endif %}
|
|
|
|
|
21 |
*
|
22 |
* @author Fabien Potencier <fabien@symfony.com>
|
23 |
*/
|
24 |
+
class Twig_Node_Expression_Test_Constant extends TestExpression
|
25 |
{
|
26 |
+
public function compile(Compiler $compiler)
|
27 |
{
|
28 |
$compiler
|
29 |
->raw('(')
|
vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.php
CHANGED
@@ -9,50 +9,58 @@
|
|
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 |
-
*
|
16 |
-
*
|
17 |
-
*
|
18 |
-
*
|
19 |
-
* {% endif %}
|
20 |
-
* </pre>
|
21 |
*
|
22 |
* @author Fabien Potencier <fabien@symfony.com>
|
23 |
*/
|
24 |
-
class Twig_Node_Expression_Test_Defined extends
|
25 |
{
|
26 |
public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
|
27 |
{
|
28 |
-
if ($node instanceof
|
29 |
$node->setAttribute('is_defined_test', true);
|
30 |
-
} elseif ($node instanceof
|
31 |
$node->setAttribute('is_defined_test', true);
|
32 |
$this->changeIgnoreStrictCheck($node);
|
33 |
-
} elseif ($node instanceof
|
34 |
$node->setAttribute('is_defined_test', true);
|
35 |
-
} elseif ($node instanceof
|
36 |
$node->setAttribute('is_defined_test', true);
|
37 |
-
} elseif ($node instanceof
|
38 |
-
$node = new
|
39 |
} else {
|
40 |
-
throw new
|
41 |
}
|
42 |
|
43 |
parent::__construct($node, $name, $arguments, $lineno);
|
44 |
}
|
45 |
|
46 |
-
protected function changeIgnoreStrictCheck(
|
47 |
{
|
48 |
$node->setAttribute('ignore_strict_check', true);
|
49 |
|
50 |
-
if ($node->getNode('node') instanceof
|
51 |
$this->changeIgnoreStrictCheck($node->getNode('node'));
|
52 |
}
|
53 |
}
|
54 |
|
55 |
-
public function compile(
|
56 |
{
|
57 |
$compiler->subcompile($this->getNode('node'));
|
58 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Error\SyntaxError;
|
14 |
+
use Twig\Node\Expression\ArrayExpression;
|
15 |
+
use Twig\Node\Expression\BlockReferenceExpression;
|
16 |
+
use Twig\Node\Expression\ConstantExpression;
|
17 |
+
use Twig\Node\Expression\FunctionExpression;
|
18 |
+
use Twig\Node\Expression\GetAttrExpression;
|
19 |
+
use Twig\Node\Expression\NameExpression;
|
20 |
+
use Twig\Node\Expression\TestExpression;
|
21 |
+
|
22 |
/**
|
23 |
* Checks if a variable is defined in the current context.
|
24 |
*
|
25 |
+
* {# defined works with variable names and variable attributes #}
|
26 |
+
* {% if foo is defined %}
|
27 |
+
* {# ... #}
|
28 |
+
* {% endif %}
|
|
|
|
|
29 |
*
|
30 |
* @author Fabien Potencier <fabien@symfony.com>
|
31 |
*/
|
32 |
+
class Twig_Node_Expression_Test_Defined extends TestExpression
|
33 |
{
|
34 |
public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
|
35 |
{
|
36 |
+
if ($node instanceof NameExpression) {
|
37 |
$node->setAttribute('is_defined_test', true);
|
38 |
+
} elseif ($node instanceof GetAttrExpression) {
|
39 |
$node->setAttribute('is_defined_test', true);
|
40 |
$this->changeIgnoreStrictCheck($node);
|
41 |
+
} elseif ($node instanceof BlockReferenceExpression) {
|
42 |
$node->setAttribute('is_defined_test', true);
|
43 |
+
} elseif ($node instanceof FunctionExpression && 'constant' === $node->getAttribute('name')) {
|
44 |
$node->setAttribute('is_defined_test', true);
|
45 |
+
} elseif ($node instanceof ConstantExpression || $node instanceof ArrayExpression) {
|
46 |
+
$node = new ConstantExpression(true, $node->getTemplateLine());
|
47 |
} else {
|
48 |
+
throw new SyntaxError('The "defined" test only works with simple variables.', $this->getTemplateLine());
|
49 |
}
|
50 |
|
51 |
parent::__construct($node, $name, $arguments, $lineno);
|
52 |
}
|
53 |
|
54 |
+
protected function changeIgnoreStrictCheck(GetAttrExpression $node)
|
55 |
{
|
56 |
$node->setAttribute('ignore_strict_check', true);
|
57 |
|
58 |
+
if ($node->getNode('node') instanceof GetAttrExpression) {
|
59 |
$this->changeIgnoreStrictCheck($node->getNode('node'));
|
60 |
}
|
61 |
}
|
62 |
|
63 |
+
public function compile(Compiler $compiler)
|
64 |
{
|
65 |
$compiler->subcompile($this->getNode('node'));
|
66 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Test/Divisibleby.php
CHANGED
@@ -9,18 +9,19 @@
|
|
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
|
22 |
{
|
23 |
-
public function compile(
|
24 |
{
|
25 |
$compiler
|
26 |
->raw('(0 == ')
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\TestExpression;
|
14 |
+
|
15 |
/**
|
16 |
* Checks if a variable is divisible by a number.
|
17 |
*
|
|
|
18 |
* {% if loop.index is divisible by(3) %}
|
|
|
19 |
*
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
+
class Twig_Node_Expression_Test_Divisibleby extends TestExpression
|
23 |
{
|
24 |
+
public function compile(Compiler $compiler)
|
25 |
{
|
26 |
$compiler
|
27 |
->raw('(0 == ')
|
vendor/twig/twig/lib/Twig/Node/Expression/Test/Even.php
CHANGED
@@ -9,18 +9,19 @@
|
|
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
|
22 |
{
|
23 |
-
public function compile(
|
24 |
{
|
25 |
$compiler
|
26 |
->raw('(')
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\TestExpression;
|
14 |
+
|
15 |
/**
|
16 |
* Checks if a number is even.
|
17 |
*
|
|
|
18 |
* {{ var is even }}
|
|
|
19 |
*
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
+
class Twig_Node_Expression_Test_Even extends TestExpression
|
23 |
{
|
24 |
+
public function compile(Compiler $compiler)
|
25 |
{
|
26 |
$compiler
|
27 |
->raw('(')
|
vendor/twig/twig/lib/Twig/Node/Expression/Test/Null.php
CHANGED
@@ -9,18 +9,19 @@
|
|
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
|
22 |
{
|
23 |
-
public function compile(
|
24 |
{
|
25 |
$compiler
|
26 |
->raw('(null === ')
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\TestExpression;
|
14 |
+
|
15 |
/**
|
16 |
* Checks that a variable is null.
|
17 |
*
|
|
|
18 |
* {{ var is none }}
|
|
|
19 |
*
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
+
class Twig_Node_Expression_Test_Null extends TestExpression
|
23 |
{
|
24 |
+
public function compile(Compiler $compiler)
|
25 |
{
|
26 |
$compiler
|
27 |
->raw('(null === ')
|
vendor/twig/twig/lib/Twig/Node/Expression/Test/Odd.php
CHANGED
@@ -9,18 +9,19 @@
|
|
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
|
22 |
{
|
23 |
-
public function compile(
|
24 |
{
|
25 |
$compiler
|
26 |
->raw('(')
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\TestExpression;
|
14 |
+
|
15 |
/**
|
16 |
* Checks if a number is odd.
|
17 |
*
|
|
|
18 |
* {{ var is odd }}
|
|
|
19 |
*
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
+
class Twig_Node_Expression_Test_Odd extends TestExpression
|
23 |
{
|
24 |
+
public function compile(Compiler $compiler)
|
25 |
{
|
26 |
$compiler
|
27 |
->raw('(')
|
vendor/twig/twig/lib/Twig/Node/Expression/Test/Sameas.php
CHANGED
@@ -9,14 +9,17 @@
|
|
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
|
18 |
{
|
19 |
-
public function compile(
|
20 |
{
|
21 |
$compiler
|
22 |
->raw('(')
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\TestExpression;
|
14 |
+
|
15 |
/**
|
16 |
* Checks if a variable is the same as another one (=== in PHP).
|
17 |
*
|
18 |
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
*/
|
20 |
+
class Twig_Node_Expression_Test_Sameas extends TestExpression
|
21 |
{
|
22 |
+
public function compile(Compiler $compiler)
|
23 |
{
|
24 |
$compiler
|
25 |
->raw('(')
|
vendor/twig/twig/lib/Twig/Node/Expression/Unary.php
CHANGED
@@ -9,21 +9,25 @@
|
|
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 |
public function __construct(Twig_NodeInterface $node, $lineno)
|
15 |
{
|
16 |
parent::__construct(['node' => $node], [], $lineno);
|
17 |
}
|
18 |
|
19 |
-
public function compile(
|
20 |
{
|
21 |
$compiler->raw(' ');
|
22 |
$this->operator($compiler);
|
23 |
$compiler->subcompile($this->getNode('node'));
|
24 |
}
|
25 |
|
26 |
-
abstract public function operator(
|
27 |
}
|
28 |
|
29 |
class_alias('Twig_Node_Expression_Unary', 'Twig\Node\Expression\Unary\AbstractUnary', false);
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\AbstractExpression;
|
15 |
+
|
16 |
+
abstract class Twig_Node_Expression_Unary extends AbstractExpression
|
17 |
{
|
18 |
public function __construct(Twig_NodeInterface $node, $lineno)
|
19 |
{
|
20 |
parent::__construct(['node' => $node], [], $lineno);
|
21 |
}
|
22 |
|
23 |
+
public function compile(Compiler $compiler)
|
24 |
{
|
25 |
$compiler->raw(' ');
|
26 |
$this->operator($compiler);
|
27 |
$compiler->subcompile($this->getNode('node'));
|
28 |
}
|
29 |
|
30 |
+
abstract public function operator(Compiler $compiler);
|
31 |
}
|
32 |
|
33 |
class_alias('Twig_Node_Expression_Unary', 'Twig\Node\Expression\Unary\AbstractUnary', false);
|
vendor/twig/twig/lib/Twig/Node/Expression/Unary/Neg.php
CHANGED
@@ -9,9 +9,13 @@
|
|
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 |
-
public function operator(
|
15 |
{
|
16 |
$compiler->raw('-');
|
17 |
}
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\Unary\AbstractUnary;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Unary_Neg extends AbstractUnary
|
17 |
{
|
18 |
+
public function operator(Compiler $compiler)
|
19 |
{
|
20 |
$compiler->raw('-');
|
21 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Unary/Not.php
CHANGED
@@ -9,9 +9,13 @@
|
|
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 |
-
public function operator(
|
15 |
{
|
16 |
$compiler->raw('!');
|
17 |
}
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\Unary\AbstractUnary;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Unary_Not extends AbstractUnary
|
17 |
{
|
18 |
+
public function operator(Compiler $compiler)
|
19 |
{
|
20 |
$compiler->raw('!');
|
21 |
}
|
vendor/twig/twig/lib/Twig/Node/Expression/Unary/Pos.php
CHANGED
@@ -9,9 +9,13 @@
|
|
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 |
-
public function operator(
|
15 |
{
|
16 |
$compiler->raw('+');
|
17 |
}
|
9 |
* For the full copyright and license information, please view the LICENSE
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
+
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\Unary\AbstractUnary;
|
15 |
+
|
16 |
+
class Twig_Node_Expression_Unary_Pos extends AbstractUnary
|
17 |
{
|
18 |
+
public function operator(Compiler $compiler)
|
19 |
{
|
20 |
$compiler->raw('+');
|
21 |
}
|
vendor/twig/twig/lib/Twig/Node/Flush.php
CHANGED
@@ -9,19 +9,22 @@
|
|
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
|
18 |
{
|
19 |
public function __construct($lineno, $tag)
|
20 |
{
|
21 |
parent::__construct([], [], $lineno, $tag);
|
22 |
}
|
23 |
|
24 |
-
public function compile(
|
25 |
{
|
26 |
$compiler
|
27 |
->addDebugInfo($this)
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Node;
|
14 |
+
|
15 |
/**
|
16 |
* Represents a flush node.
|
17 |
*
|
18 |
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
*/
|
20 |
+
class Twig_Node_Flush extends Node
|
21 |
{
|
22 |
public function __construct($lineno, $tag)
|
23 |
{
|
24 |
parent::__construct([], [], $lineno, $tag);
|
25 |
}
|
26 |
|
27 |
+
public function compile(Compiler $compiler)
|
28 |
{
|
29 |
$compiler
|
30 |
->addDebugInfo($this)
|
vendor/twig/twig/lib/Twig/Node/For.php
CHANGED
@@ -10,21 +10,28 @@
|
|
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
|
19 |
{
|
20 |
protected $loop;
|
21 |
|
22 |
-
public function __construct(
|
23 |
{
|
24 |
-
$body = new
|
25 |
|
26 |
if (null !== $ifexpr) {
|
27 |
-
$body = new
|
28 |
}
|
29 |
|
30 |
$nodes = ['key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body];
|
@@ -35,7 +42,7 @@ class Twig_Node_For extends Twig_Node
|
|
35 |
parent::__construct($nodes, ['with_loop' => true, 'ifexpr' => null !== $ifexpr], $lineno, $tag);
|
36 |
}
|
37 |
|
38 |
-
public function compile(
|
39 |
{
|
40 |
$compiler
|
41 |
->addDebugInfo($this)
|
@@ -61,7 +68,7 @@ class Twig_Node_For extends Twig_Node
|
|
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")
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\AbstractExpression;
|
15 |
+
use Twig\Node\Expression\AssignNameExpression;
|
16 |
+
use Twig\Node\ForLoopNode;
|
17 |
+
use Twig\Node\IfNode;
|
18 |
+
use Twig\Node\Node;
|
19 |
+
|
20 |
/**
|
21 |
* Represents a for node.
|
22 |
*
|
23 |
* @author Fabien Potencier <fabien@symfony.com>
|
24 |
*/
|
25 |
+
class Twig_Node_For extends Node
|
26 |
{
|
27 |
protected $loop;
|
28 |
|
29 |
+
public function __construct(AssignNameExpression $keyTarget, AssignNameExpression $valueTarget, AbstractExpression $seq, AbstractExpression $ifexpr = null, Twig_NodeInterface $body, Twig_NodeInterface $else = null, $lineno, $tag = null)
|
30 |
{
|
31 |
+
$body = new Node([$body, $this->loop = new ForLoopNode($lineno, $tag)]);
|
32 |
|
33 |
if (null !== $ifexpr) {
|
34 |
+
$body = new IfNode(new Node([$ifexpr, $body]), null, $lineno, $tag);
|
35 |
}
|
36 |
|
37 |
$nodes = ['key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body];
|
42 |
parent::__construct($nodes, ['with_loop' => true, 'ifexpr' => null !== $ifexpr], $lineno, $tag);
|
43 |
}
|
44 |
|
45 |
+
public function compile(Compiler $compiler)
|
46 |
{
|
47 |
$compiler
|
48 |
->addDebugInfo($this)
|
68 |
|
69 |
if (!$this->getAttribute('ifexpr')) {
|
70 |
$compiler
|
71 |
+
->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof \Countable)) {\n")
|
72 |
->indent()
|
73 |
->write("\$length = count(\$context['_seq']);\n")
|
74 |
->write("\$context['loop']['revindex0'] = \$length - 1;\n")
|
vendor/twig/twig/lib/Twig/Node/ForLoop.php
CHANGED
@@ -9,19 +9,22 @@
|
|
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
|
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(
|
25 |
{
|
26 |
if ($this->getAttribute('else')) {
|
27 |
$compiler->write("\$context['_iterated'] = true;\n");
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Node;
|
14 |
+
|
15 |
/**
|
16 |
* Internal node used by the for node.
|
17 |
*
|
18 |
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
*/
|
20 |
+
class Twig_Node_ForLoop extends Node
|
21 |
{
|
22 |
public function __construct($lineno, $tag = null)
|
23 |
{
|
24 |
parent::__construct([], ['with_loop' => false, 'ifexpr' => false, 'else' => false], $lineno, $tag);
|
25 |
}
|
26 |
|
27 |
+
public function compile(Compiler $compiler)
|
28 |
{
|
29 |
if ($this->getAttribute('else')) {
|
30 |
$compiler->write("\$context['_iterated'] = true;\n");
|
vendor/twig/twig/lib/Twig/Node/If.php
CHANGED
@@ -10,12 +10,15 @@
|
|
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
|
19 |
{
|
20 |
public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else = null, $lineno, $tag = null)
|
21 |
{
|
@@ -27,10 +30,10 @@ class Twig_Node_If extends Twig_Node
|
|
27 |
parent::__construct($nodes, [], $lineno, $tag);
|
28 |
}
|
29 |
|
30 |
-
public function compile(
|
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()
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Node;
|
15 |
+
|
16 |
/**
|
17 |
* Represents an if node.
|
18 |
*
|
19 |
* @author Fabien Potencier <fabien@symfony.com>
|
20 |
*/
|
21 |
+
class Twig_Node_If extends Node
|
22 |
{
|
23 |
public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else = null, $lineno, $tag = null)
|
24 |
{
|
30 |
parent::__construct($nodes, [], $lineno, $tag);
|
31 |
}
|
32 |
|
33 |
+
public function compile(Compiler $compiler)
|
34 |
{
|
35 |
$compiler->addDebugInfo($this);
|
36 |
+
for ($i = 0, $count = \count($this->getNode('tests')); $i < $count; $i += 2) {
|
37 |
if ($i > 0) {
|
38 |
$compiler
|
39 |
->outdent()
|
vendor/twig/twig/lib/Twig/Node/Import.php
CHANGED
@@ -9,19 +9,24 @@
|
|
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
|
18 |
{
|
19 |
-
public function __construct(
|
20 |
{
|
21 |
parent::__construct(['expr' => $expr, 'var' => $var], [], $lineno, $tag);
|
22 |
}
|
23 |
|
24 |
-
public function compile(
|
25 |
{
|
26 |
$compiler
|
27 |
->addDebugInfo($this)
|
@@ -30,7 +35,7 @@ class Twig_Node_Import extends Twig_Node
|
|
30 |
->raw(' = ')
|
31 |
;
|
32 |
|
33 |
-
if ($this->getNode('expr') instanceof
|
34 |
$compiler->raw('$this');
|
35 |
} else {
|
36 |
$compiler
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\AbstractExpression;
|
14 |
+
use Twig\Node\Expression\NameExpression;
|
15 |
+
use Twig\Node\Node;
|
16 |
+
|
17 |
/**
|
18 |
* Represents an import node.
|
19 |
*
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
+
class Twig_Node_Import extends Node
|
23 |
{
|
24 |
+
public function __construct(AbstractExpression $expr, AbstractExpression $var, $lineno, $tag = null)
|
25 |
{
|
26 |
parent::__construct(['expr' => $expr, 'var' => $var], [], $lineno, $tag);
|
27 |
}
|
28 |
|
29 |
+
public function compile(Compiler $compiler)
|
30 |
{
|
31 |
$compiler
|
32 |
->addDebugInfo($this)
|
35 |
->raw(' = ')
|
36 |
;
|
37 |
|
38 |
+
if ($this->getNode('expr') instanceof NameExpression && '_self' === $this->getNode('expr')->getAttribute('name')) {
|
39 |
$compiler->raw('$this');
|
40 |
} else {
|
41 |
$compiler
|
vendor/twig/twig/lib/Twig/Node/Include.php
CHANGED
@@ -10,14 +10,19 @@
|
|
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
|
19 |
{
|
20 |
-
public function __construct(
|
21 |
{
|
22 |
$nodes = ['expr' => $expr];
|
23 |
if (null !== $variables) {
|
@@ -27,7 +32,7 @@ class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface
|
|
27 |
parent::__construct($nodes, ['only' => (bool) $only, 'ignore_missing' => (bool) $ignoreMissing], $lineno, $tag);
|
28 |
}
|
29 |
|
30 |
-
public function compile(
|
31 |
{
|
32 |
$compiler->addDebugInfo($this);
|
33 |
|
@@ -49,7 +54,7 @@ class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface
|
|
49 |
if ($this->getAttribute('ignore_missing')) {
|
50 |
$compiler
|
51 |
->outdent()
|
52 |
-
->write("} catch (
|
53 |
->indent()
|
54 |
->write("// ignore missing template\n")
|
55 |
->outdent()
|
@@ -58,7 +63,7 @@ class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface
|
|
58 |
}
|
59 |
}
|
60 |
|
61 |
-
protected function addGetTemplate(
|
62 |
{
|
63 |
$compiler
|
64 |
->write('$this->loadTemplate(')
|
@@ -71,7 +76,7 @@ class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface
|
|
71 |
;
|
72 |
}
|
73 |
|
74 |
-
protected function addTemplateArguments(
|
75 |
{
|
76 |
if (!$this->hasNode('variables')) {
|
77 |
$compiler->raw(false === $this->getAttribute('only') ? '$context' : '[]');
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\AbstractExpression;
|
15 |
+
use Twig\Node\Node;
|
16 |
+
use Twig\Node\NodeOutputInterface;
|
17 |
+
|
18 |
/**
|
19 |
* Represents an include node.
|
20 |
*
|
21 |
* @author Fabien Potencier <fabien@symfony.com>
|
22 |
*/
|
23 |
+
class Twig_Node_Include extends Node implements NodeOutputInterface
|
24 |
{
|
25 |
+
public function __construct(AbstractExpression $expr, AbstractExpression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
|
26 |
{
|
27 |
$nodes = ['expr' => $expr];
|
28 |
if (null !== $variables) {
|
32 |
parent::__construct($nodes, ['only' => (bool) $only, 'ignore_missing' => (bool) $ignoreMissing], $lineno, $tag);
|
33 |
}
|
34 |
|
35 |
+
public function compile(Compiler $compiler)
|
36 |
{
|
37 |
$compiler->addDebugInfo($this);
|
38 |
|
54 |
if ($this->getAttribute('ignore_missing')) {
|
55 |
$compiler
|
56 |
->outdent()
|
57 |
+
->write("} catch (LoaderError \$e) {\n")
|
58 |
->indent()
|
59 |
->write("// ignore missing template\n")
|
60 |
->outdent()
|
63 |
}
|
64 |
}
|
65 |
|
66 |
+
protected function addGetTemplate(Compiler $compiler)
|
67 |
{
|
68 |
$compiler
|
69 |
->write('$this->loadTemplate(')
|
76 |
;
|
77 |
}
|
78 |
|
79 |
+
protected function addTemplateArguments(Compiler $compiler)
|
80 |
{
|
81 |
if (!$this->hasNode('variables')) {
|
82 |
$compiler->raw(false === $this->getAttribute('only') ? '$context' : '[]');
|
vendor/twig/twig/lib/Twig/Node/Macro.php
CHANGED
@@ -9,12 +9,16 @@
|
|
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
|
18 |
{
|
19 |
const VARARGS_NAME = 'varargs';
|
20 |
|
@@ -22,21 +26,21 @@ class Twig_Node_Macro extends Twig_Node
|
|
22 |
{
|
23 |
foreach ($arguments as $argumentName => $argument) {
|
24 |
if (self::VARARGS_NAME === $argumentName) {
|
25 |
-
throw new
|
26 |
}
|
27 |
}
|
28 |
|
29 |
parent::__construct(['body' => $body, 'arguments' => $arguments], ['name' => $name], $lineno, $tag);
|
30 |
}
|
31 |
|
32 |
-
public function compile(
|
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
|
@@ -104,18 +108,18 @@ class Twig_Node_Macro extends Twig_Node
|
|
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
|
119 |
->outdent()
|
120 |
->write("}\n\n")
|
121 |
;
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Error\SyntaxError;
|
14 |
+
use Twig\Node\Node;
|
15 |
+
|
16 |
/**
|
17 |
* Represents a macro node.
|
18 |
*
|
19 |
* @author Fabien Potencier <fabien@symfony.com>
|
20 |
*/
|
21 |
+
class Twig_Node_Macro extends Node
|
22 |
{
|
23 |
const VARARGS_NAME = 'varargs';
|
24 |
|
26 |
{
|
27 |
foreach ($arguments as $argumentName => $argument) {
|
28 |
if (self::VARARGS_NAME === $argumentName) {
|
29 |
+
throw new SyntaxError(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());
|
30 |
}
|
31 |
}
|
32 |
|
33 |
parent::__construct(['body' => $body, 'arguments' => $arguments], ['name' => $name], $lineno, $tag);
|
34 |
}
|
35 |
|
36 |
+
public function compile(Compiler $compiler)
|
37 |
{
|
38 |
$compiler
|
39 |
->addDebugInfo($this)
|
40 |
->write(sprintf('public function get%s(', $this->getAttribute('name')))
|
41 |
;
|
42 |
|
43 |
+
$count = \count($this->getNode('arguments'));
|
44 |
$pos = 0;
|
45 |
foreach ($this->getNode('arguments') as $name => $default) {
|
46 |
$compiler
|
108 |
->indent()
|
109 |
->subcompile($this->getNode('body'))
|
110 |
->outdent()
|
111 |
+
->write("} catch (\Exception \$e) {\n")
|
112 |
->indent()
|
113 |
->write("ob_end_clean();\n\n")
|
114 |
->write("throw \$e;\n")
|
115 |
->outdent()
|
116 |
+
->write("} catch (\Throwable \$e) {\n")
|
117 |
->indent()
|
118 |
->write("ob_end_clean();\n\n")
|
119 |
->write("throw \$e;\n")
|
120 |
->outdent()
|
121 |
->write("}\n\n")
|
122 |
+
->write("return ('' === \$tmp = ob_get_clean()) ? '' : new Markup(\$tmp, \$this->env->getCharset());\n")
|
123 |
->outdent()
|
124 |
->write("}\n\n")
|
125 |
;
|
vendor/twig/twig/lib/Twig/Node/Module.php
CHANGED
@@ -10,6 +10,15 @@
|
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
/**
|
14 |
* Represents a module node.
|
15 |
*
|
@@ -19,15 +28,15 @@
|
|
19 |
*
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
-
class Twig_Node_Module extends
|
23 |
{
|
24 |
private $source;
|
25 |
|
26 |
-
public function __construct(Twig_NodeInterface $body,
|
27 |
{
|
28 |
-
if (!$name instanceof
|
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
|
31 |
} else {
|
32 |
$this->source = $name;
|
33 |
}
|
@@ -37,11 +46,11 @@ class Twig_Node_Module extends Twig_Node
|
|
37 |
'blocks' => $blocks,
|
38 |
'macros' => $macros,
|
39 |
'traits' => $traits,
|
40 |
-
'display_start' => new
|
41 |
-
'display_end' => new
|
42 |
-
'constructor_start' => new
|
43 |
-
'constructor_end' => new
|
44 |
-
'class_end' => new
|
45 |
];
|
46 |
if (null !== $parent) {
|
47 |
$nodes['parent'] = $parent;
|
@@ -66,7 +75,7 @@ class Twig_Node_Module extends Twig_Node
|
|
66 |
$this->setAttribute('index', $index);
|
67 |
}
|
68 |
|
69 |
-
public function compile(
|
70 |
{
|
71 |
$this->compileTemplate($compiler);
|
72 |
|
@@ -75,7 +84,7 @@ class Twig_Node_Module extends Twig_Node
|
|
75 |
}
|
76 |
}
|
77 |
|
78 |
-
protected function compileTemplate(
|
79 |
{
|
80 |
if (!$this->getAttribute('index')) {
|
81 |
$compiler->write('<?php');
|
@@ -84,12 +93,12 @@ class Twig_Node_Module extends Twig_Node
|
|
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
|
91 |
-
|| count($this->getNode('constructor_start'))
|
92 |
-
|| count($this->getNode('constructor_end'))
|
93 |
) {
|
94 |
$this->compileConstructor($compiler);
|
95 |
}
|
@@ -115,7 +124,7 @@ class Twig_Node_Module extends Twig_Node
|
|
115 |
$this->compileClassFooter($compiler);
|
116 |
}
|
117 |
|
118 |
-
protected function compileGetParent(
|
119 |
{
|
120 |
if (!$this->hasNode('parent')) {
|
121 |
return;
|
@@ -129,7 +138,7 @@ class Twig_Node_Module extends Twig_Node
|
|
129 |
->write('return ')
|
130 |
;
|
131 |
|
132 |
-
if ($parent instanceof
|
133 |
$compiler->subcompile($parent);
|
134 |
} else {
|
135 |
$compiler
|
@@ -150,10 +159,26 @@ class Twig_Node_Module extends Twig_Node
|
|
150 |
;
|
151 |
}
|
152 |
|
153 |
-
protected function compileClassHeader(
|
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')))
|
@@ -163,10 +188,10 @@ class Twig_Node_Module extends Twig_Node
|
|
163 |
;
|
164 |
}
|
165 |
|
166 |
-
protected function compileConstructor(
|
167 |
{
|
168 |
$compiler
|
169 |
-
->write("public function __construct(
|
170 |
->indent()
|
171 |
->subcompile($this->getNode('constructor_start'))
|
172 |
->write("parent::__construct(\$env);\n\n")
|
@@ -175,7 +200,7 @@ class Twig_Node_Module extends Twig_Node
|
|
175 |
// parent
|
176 |
if (!$this->hasNode('parent')) {
|
177 |
$compiler->write("\$this->parent = false;\n\n");
|
178 |
-
} elseif (($parent = $this->getNode('parent')) && $parent instanceof
|
179 |
$compiler
|
180 |
->addDebugInfo($parent)
|
181 |
->write('$this->parent = $this->loadTemplate(')
|
@@ -188,7 +213,7 @@ class Twig_Node_Module extends Twig_Node
|
|
188 |
;
|
189 |
}
|
190 |
|
191 |
-
$countTraits = count($this->getNode('traits'));
|
192 |
if ($countTraits) {
|
193 |
// traits
|
194 |
foreach ($this->getNode('traits') as $i => $trait) {
|
@@ -198,7 +223,7 @@ class Twig_Node_Module extends Twig_Node
|
|
198 |
->addDebugInfo($trait->getNode('template'))
|
199 |
->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i))
|
200 |
->indent()
|
201 |
-
->write("throw new
|
202 |
->subcompile($trait->getNode('template'))
|
203 |
->raw(".'\" cannot be used as a trait.');\n")
|
204 |
->outdent()
|
@@ -212,7 +237,7 @@ class Twig_Node_Module extends Twig_Node
|
|
212 |
->string($key)
|
213 |
->raw("])) {\n")
|
214 |
->indent()
|
215 |
-
->write("throw new
|
216 |
->string($key)
|
217 |
->raw(' is not defined in trait ')
|
218 |
->subcompile($trait->getNode('template'))
|
@@ -297,7 +322,7 @@ class Twig_Node_Module extends Twig_Node
|
|
297 |
;
|
298 |
}
|
299 |
|
300 |
-
protected function compileDisplay(
|
301 |
{
|
302 |
$compiler
|
303 |
->write("protected function doDisplay(array \$context, array \$blocks = [])\n", "{\n")
|
@@ -309,7 +334,7 @@ class Twig_Node_Module extends Twig_Node
|
|
309 |
if ($this->hasNode('parent')) {
|
310 |
$parent = $this->getNode('parent');
|
311 |
$compiler->addDebugInfo($parent);
|
312 |
-
if ($parent instanceof
|
313 |
$compiler->write('$this->parent');
|
314 |
} else {
|
315 |
$compiler->write('$this->getParent($context)');
|
@@ -324,7 +349,7 @@ class Twig_Node_Module extends Twig_Node
|
|
324 |
;
|
325 |
}
|
326 |
|
327 |
-
protected function compileClassFooter(
|
328 |
{
|
329 |
$compiler
|
330 |
->subcompile($this->getNode('class_end'))
|
@@ -333,12 +358,12 @@ class Twig_Node_Module extends Twig_Node
|
|
333 |
;
|
334 |
}
|
335 |
|
336 |
-
protected function compileMacros(
|
337 |
{
|
338 |
$compiler->subcompile($this->getNode('macros'));
|
339 |
}
|
340 |
|
341 |
-
protected function compileGetTemplateName(
|
342 |
{
|
343 |
$compiler
|
344 |
->write("public function getTemplateName()\n", "{\n")
|
@@ -351,7 +376,7 @@ class Twig_Node_Module extends Twig_Node
|
|
351 |
;
|
352 |
}
|
353 |
|
354 |
-
protected function compileIsTraitable(
|
355 |
{
|
356 |
// A template can be used as a trait if:
|
357 |
// * it has no parent
|
@@ -360,28 +385,28 @@ class Twig_Node_Module extends Twig_Node
|
|
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
|
366 |
$nodes = $this->getNode('body')->getNode(0);
|
367 |
} else {
|
368 |
$nodes = $this->getNode('body');
|
369 |
}
|
370 |
|
371 |
-
if (
|
372 |
-
$nodes = new
|
373 |
}
|
374 |
|
375 |
foreach ($nodes as $node) {
|
376 |
-
if (
|
377 |
continue;
|
378 |
}
|
379 |
|
380 |
-
if ($node instanceof
|
381 |
continue;
|
382 |
}
|
383 |
|
384 |
-
if ($node instanceof
|
385 |
continue;
|
386 |
}
|
387 |
|
@@ -403,7 +428,7 @@ class Twig_Node_Module extends Twig_Node
|
|
403 |
;
|
404 |
}
|
405 |
|
406 |
-
protected function compileDebugInfo(
|
407 |
{
|
408 |
$compiler
|
409 |
->write("public function getDebugInfo()\n", "{\n")
|
@@ -414,7 +439,7 @@ class Twig_Node_Module extends Twig_Node
|
|
414 |
;
|
415 |
}
|
416 |
|
417 |
-
protected function compileGetSource(
|
418 |
{
|
419 |
$compiler
|
420 |
->write("/** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */\n")
|
@@ -428,12 +453,12 @@ class Twig_Node_Module extends Twig_Node
|
|
428 |
;
|
429 |
}
|
430 |
|
431 |
-
protected function compileGetSourceContext(
|
432 |
{
|
433 |
$compiler
|
434 |
->write("public function getSourceContext()\n", "{\n")
|
435 |
->indent()
|
436 |
-
->write('return new
|
437 |
->string($compiler->getEnvironment()->isDebug() ? $this->source->getCode() : '')
|
438 |
->raw(', ')
|
439 |
->string($this->source->getName())
|
@@ -445,9 +470,9 @@ class Twig_Node_Module extends Twig_Node
|
|
445 |
;
|
446 |
}
|
447 |
|
448 |
-
protected function compileLoadTemplate(
|
449 |
{
|
450 |
-
if ($node instanceof
|
451 |
$compiler
|
452 |
->write(sprintf('%s = $this->loadTemplate(', $var))
|
453 |
->subcompile($node)
|
@@ -458,7 +483,7 @@ class Twig_Node_Module extends Twig_Node
|
|
458 |
->raw(");\n")
|
459 |
;
|
460 |
} else {
|
461 |
-
throw new LogicException('Trait templates can only be constant nodes.');
|
462 |
}
|
463 |
}
|
464 |
}
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\BlockReferenceNode;
|
15 |
+
use Twig\Node\BodyNode;
|
16 |
+
use Twig\Node\Expression\AbstractExpression;
|
17 |
+
use Twig\Node\Expression\ConstantExpression;
|
18 |
+
use Twig\Node\Node;
|
19 |
+
use Twig\Node\TextNode;
|
20 |
+
use Twig\Source;
|
21 |
+
|
22 |
/**
|
23 |
* Represents a module node.
|
24 |
*
|
28 |
*
|
29 |
* @author Fabien Potencier <fabien@symfony.com>
|
30 |
*/
|
31 |
+
class Twig_Node_Module extends Node
|
32 |
{
|
33 |
private $source;
|
34 |
|
35 |
+
public function __construct(Twig_NodeInterface $body, AbstractExpression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $name, $source = '')
|
36 |
{
|
37 |
+
if (!$name instanceof Source) {
|
38 |
@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);
|
39 |
+
$this->source = new Source($source, $name);
|
40 |
} else {
|
41 |
$this->source = $name;
|
42 |
}
|
46 |
'blocks' => $blocks,
|
47 |
'macros' => $macros,
|
48 |
'traits' => $traits,
|
49 |
+
'display_start' => new Node(),
|
50 |
+
'display_end' => new Node(),
|
51 |
+
'constructor_start' => new Node(),
|
52 |
+
'constructor_end' => new Node(),
|
53 |
+
'class_end' => new Node(),
|
54 |
];
|
55 |
if (null !== $parent) {
|
56 |
$nodes['parent'] = $parent;
|
75 |
$this->setAttribute('index', $index);
|
76 |
}
|
77 |
|
78 |
+
public function compile(Compiler $compiler)
|
79 |
{
|
80 |
$this->compileTemplate($compiler);
|
81 |
|
84 |
}
|
85 |
}
|
86 |
|
87 |
+
protected function compileTemplate(Compiler $compiler)
|
88 |
{
|
89 |
if (!$this->getAttribute('index')) {
|
90 |
$compiler->write('<?php');
|
93 |
$this->compileClassHeader($compiler);
|
94 |
|
95 |
if (
|
96 |
+
\count($this->getNode('blocks'))
|
97 |
+
|| \count($this->getNode('traits'))
|
98 |
|| !$this->hasNode('parent')
|
99 |
+
|| $this->getNode('parent') instanceof ConstantExpression
|
100 |
+
|| \count($this->getNode('constructor_start'))
|
101 |
+
|| \count($this->getNode('constructor_end'))
|
102 |
) {
|
103 |
$this->compileConstructor($compiler);
|
104 |
}
|
124 |
$this->compileClassFooter($compiler);
|
125 |
}
|
126 |
|
127 |
+
protected function compileGetParent(Compiler $compiler)
|
128 |
{
|
129 |
if (!$this->hasNode('parent')) {
|
130 |
return;
|
138 |
->write('return ')
|
139 |
;
|
140 |
|
141 |
+
if ($parent instanceof ConstantExpression) {
|
142 |
$compiler->subcompile($parent);
|
143 |
} else {
|
144 |
$compiler
|
159 |
;
|
160 |
}
|
161 |
|
162 |
+
protected function compileClassHeader(Compiler $compiler)
|
163 |
{
|
164 |
$compiler
|
165 |
->write("\n\n")
|
166 |
+
;
|
167 |
+
if (!$this->getAttribute('index')) {
|
168 |
+
$compiler
|
169 |
+
->write("use Twig\Environment;\n")
|
170 |
+
->write("use Twig\Error\LoaderError;\n")
|
171 |
+
->write("use Twig\Error\RuntimeError;\n")
|
172 |
+
->write("use Twig\Markup;\n")
|
173 |
+
->write("use Twig\Sandbox\SecurityError;\n")
|
174 |
+
->write("use Twig\Sandbox\SecurityNotAllowedTagError;\n")
|
175 |
+
->write("use Twig\Sandbox\SecurityNotAllowedFilterError;\n")
|
176 |
+
->write("use Twig\Sandbox\SecurityNotAllowedFunctionError;\n")
|
177 |
+
->write("use Twig\Source;\n")
|
178 |
+
->write("use Twig\Template;\n\n")
|
179 |
+
;
|
180 |
+
}
|
181 |
+
$compiler
|
182 |
// if the template name contains */, add a blank to avoid a PHP parse error
|
183 |
->write('/* '.str_replace('*/', '* /', $this->source->getName())." */\n")
|
184 |
->write('class '.$compiler->getEnvironment()->getTemplateClass($this->source->getName(), $this->getAttribute('index')))
|
188 |
;
|
189 |
}
|
190 |
|
191 |
+
protected function compileConstructor(Compiler $compiler)
|
192 |
{
|
193 |
$compiler
|
194 |
+
->write("public function __construct(Environment \$env)\n", "{\n")
|
195 |
->indent()
|
196 |
->subcompile($this->getNode('constructor_start'))
|
197 |
->write("parent::__construct(\$env);\n\n")
|
200 |
// parent
|
201 |
if (!$this->hasNode('parent')) {
|
202 |
$compiler->write("\$this->parent = false;\n\n");
|
203 |
+
} elseif (($parent = $this->getNode('parent')) && $parent instanceof ConstantExpression) {
|
204 |
$compiler
|
205 |
->addDebugInfo($parent)
|
206 |
->write('$this->parent = $this->loadTemplate(')
|
213 |
;
|
214 |
}
|
215 |
|
216 |
+
$countTraits = \count($this->getNode('traits'));
|
217 |
if ($countTraits) {
|
218 |
// traits
|
219 |
foreach ($this->getNode('traits') as $i => $trait) {
|
223 |
->addDebugInfo($trait->getNode('template'))
|
224 |
->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i))
|
225 |
->indent()
|
226 |
+
->write("throw new RuntimeError('Template \"'.")
|
227 |
->subcompile($trait->getNode('template'))
|
228 |
->raw(".'\" cannot be used as a trait.');\n")
|
229 |
->outdent()
|
237 |
->string($key)
|
238 |
->raw("])) {\n")
|
239 |
->indent()
|
240 |
+
->write("throw new RuntimeError(sprintf('Block ")
|
241 |
->string($key)
|
242 |
->raw(' is not defined in trait ')
|
243 |
->subcompile($trait->getNode('template'))
|
322 |
;
|
323 |
}
|
324 |
|
325 |
+
protected function compileDisplay(Compiler $compiler)
|
326 |
{
|
327 |
$compiler
|
328 |
->write("protected function doDisplay(array \$context, array \$blocks = [])\n", "{\n")
|
334 |
if ($this->hasNode('parent')) {
|
335 |
$parent = $this->getNode('parent');
|
336 |
$compiler->addDebugInfo($parent);
|
337 |
+
if ($parent instanceof ConstantExpression) {
|
338 |
$compiler->write('$this->parent');
|
339 |
} else {
|
340 |
$compiler->write('$this->getParent($context)');
|
349 |
;
|
350 |
}
|
351 |
|
352 |
+
protected function compileClassFooter(Compiler $compiler)
|
353 |
{
|
354 |
$compiler
|
355 |
->subcompile($this->getNode('class_end'))
|
358 |
;
|
359 |
}
|
360 |
|
361 |
+
protected function compileMacros(Compiler $compiler)
|
362 |
{
|
363 |
$compiler->subcompile($this->getNode('macros'));
|
364 |
}
|
365 |
|
366 |
+
protected function compileGetTemplateName(Compiler $compiler)
|
367 |
{
|
368 |
$compiler
|
369 |
->write("public function getTemplateName()\n", "{\n")
|
376 |
;
|
377 |
}
|
378 |
|
379 |
+
protected function compileIsTraitable(Compiler $compiler)
|
380 |
{
|
381 |
// A template can be used as a trait if:
|
382 |
// * it has no parent
|
385 |
//
|
386 |
// Put another way, a template can be used as a trait if it
|
387 |
// only contains blocks and use statements.
|
388 |
+
$traitable = !$this->hasNode('parent') && 0 === \count($this->getNode('macros'));
|
389 |
if ($traitable) {
|
390 |
+
if ($this->getNode('body') instanceof BodyNode) {
|
391 |
$nodes = $this->getNode('body')->getNode(0);
|
392 |
} else {
|
393 |
$nodes = $this->getNode('body');
|
394 |
}
|
395 |
|
396 |
+
if (!\count($nodes)) {
|
397 |
+
$nodes = new Node([$nodes]);
|
398 |
}
|
399 |
|
400 |
foreach ($nodes as $node) {
|
401 |
+
if (!\count($node)) {
|
402 |
continue;
|
403 |
}
|
404 |
|
405 |
+
if ($node instanceof TextNode && ctype_space($node->getAttribute('data'))) {
|
406 |
continue;
|
407 |
}
|
408 |
|
409 |
+
if ($node instanceof BlockReferenceNode) {
|
410 |
continue;
|
411 |
}
|
412 |
|
428 |
;
|
429 |
}
|
430 |
|
431 |
+
protected function compileDebugInfo(Compiler $compiler)
|
432 |
{
|
433 |
$compiler
|
434 |
->write("public function getDebugInfo()\n", "{\n")
|
439 |
;
|
440 |
}
|
441 |
|
442 |
+
protected function compileGetSource(Compiler $compiler)
|
443 |
{
|
444 |
$compiler
|
445 |
->write("/** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */\n")
|
453 |
;
|
454 |
}
|
455 |
|
456 |
+
protected function compileGetSourceContext(Compiler $compiler)
|
457 |
{
|
458 |
$compiler
|
459 |
->write("public function getSourceContext()\n", "{\n")
|
460 |
->indent()
|
461 |
+
->write('return new Source(')
|
462 |
->string($compiler->getEnvironment()->isDebug() ? $this->source->getCode() : '')
|
463 |
->raw(', ')
|
464 |
->string($this->source->getName())
|
470 |
;
|
471 |
}
|
472 |
|
473 |
+
protected function compileLoadTemplate(Compiler $compiler, $node, $var)
|
474 |
{
|
475 |
+
if ($node instanceof ConstantExpression) {
|
476 |
$compiler
|
477 |
->write(sprintf('%s = $this->loadTemplate(', $var))
|
478 |
->subcompile($node)
|
483 |
->raw(");\n")
|
484 |
;
|
485 |
} else {
|
486 |
+
throw new \LogicException('Trait templates can only be constant nodes.');
|
487 |
}
|
488 |
}
|
489 |
}
|
vendor/twig/twig/lib/Twig/Node/Print.php
CHANGED
@@ -10,19 +10,24 @@
|
|
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
|
19 |
{
|
20 |
-
public function __construct(
|
21 |
{
|
22 |
parent::__construct(['expr' => $expr], [], $lineno, $tag);
|
23 |
}
|
24 |
|
25 |
-
public function compile(
|
26 |
{
|
27 |
$compiler
|
28 |
->addDebugInfo($this)
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Expression\AbstractExpression;
|
15 |
+
use Twig\Node\Node;
|
16 |
+
use Twig\Node\NodeOutputInterface;
|
17 |
+
|
18 |
/**
|
19 |
* Represents a node that outputs an expression.
|
20 |
*
|
21 |
* @author Fabien Potencier <fabien@symfony.com>
|
22 |
*/
|
23 |
+
class Twig_Node_Print extends Node implements NodeOutputInterface
|
24 |
{
|
25 |
+
public function __construct(AbstractExpression $expr, $lineno, $tag = null)
|
26 |
{
|
27 |
parent::__construct(['expr' => $expr], [], $lineno, $tag);
|
28 |
}
|
29 |
|
30 |
+
public function compile(Compiler $compiler)
|
31 |
{
|
32 |
$compiler
|
33 |
->addDebugInfo($this)
|
vendor/twig/twig/lib/Twig/Node/Sandbox.php
CHANGED
@@ -9,23 +9,26 @@
|
|
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
|
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(
|
25 |
{
|
26 |
$compiler
|
27 |
->addDebugInfo($this)
|
28 |
-
->write("\$sandbox = \$this->env->getExtension('
|
29 |
->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n")
|
30 |
->indent()
|
31 |
->write("\$sandbox->enableSandbox();\n")
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Node;
|
14 |
+
|
15 |
/**
|
16 |
* Represents a sandbox node.
|
17 |
*
|
18 |
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
*/
|
20 |
+
class Twig_Node_Sandbox extends Node
|
21 |
{
|
22 |
public function __construct(Twig_NodeInterface $body, $lineno, $tag = null)
|
23 |
{
|
24 |
parent::__construct(['body' => $body], [], $lineno, $tag);
|
25 |
}
|
26 |
|
27 |
+
public function compile(Compiler $compiler)
|
28 |
{
|
29 |
$compiler
|
30 |
->addDebugInfo($this)
|
31 |
+
->write("\$sandbox = \$this->env->getExtension('\Twig\Extension\SandboxExtension');\n")
|
32 |
->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n")
|
33 |
->indent()
|
34 |
->write("\$sandbox->enableSandbox();\n")
|
vendor/twig/twig/lib/Twig/Node/SandboxedPrint.php
CHANGED
@@ -9,6 +9,11 @@
|
|
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.
|
@@ -19,13 +24,13 @@
|
|
19 |
*
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
-
class Twig_Node_SandboxedPrint extends
|
23 |
{
|
24 |
-
public function compile(
|
25 |
{
|
26 |
$compiler
|
27 |
->addDebugInfo($this)
|
28 |
-
->write('echo $this->env->getExtension(\'
|
29 |
->subcompile($this->getNode('expr'))
|
30 |
->raw(");\n")
|
31 |
;
|
@@ -36,11 +41,11 @@ class Twig_Node_SandboxedPrint extends Twig_Node_Print
|
|
36 |
*
|
37 |
* This is mostly needed when another visitor adds filters (like the escaper one).
|
38 |
*
|
39 |
-
* @return
|
40 |
*/
|
41 |
-
protected function removeNodeFilter(
|
42 |
{
|
43 |
-
if ($node instanceof
|
44 |
return $this->removeNodeFilter($node->getNode('node'));
|
45 |
}
|
46 |
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\FilterExpression;
|
14 |
+
use Twig\Node\Node;
|
15 |
+
use Twig\Node\PrintNode;
|
16 |
+
|
17 |
/**
|
18 |
* Twig_Node_SandboxedPrint adds a check for the __toString() method
|
19 |
* when the variable is an object and the sandbox is activated.
|
24 |
*
|
25 |
* @author Fabien Potencier <fabien@symfony.com>
|
26 |
*/
|
27 |
+
class Twig_Node_SandboxedPrint extends PrintNode
|
28 |
{
|
29 |
+
public function compile(Compiler $compiler)
|
30 |
{
|
31 |
$compiler
|
32 |
->addDebugInfo($this)
|
33 |
+
->write('echo $this->env->getExtension(\'\Twig\Extension\SandboxExtension\')->ensureToStringAllowed(')
|
34 |
->subcompile($this->getNode('expr'))
|
35 |
->raw(");\n")
|
36 |
;
|
41 |
*
|
42 |
* This is mostly needed when another visitor adds filters (like the escaper one).
|
43 |
*
|
44 |
+
* @return Node
|
45 |
*/
|
46 |
+
protected function removeNodeFilter(Node $node)
|
47 |
{
|
48 |
+
if ($node instanceof FilterExpression) {
|
49 |
return $this->removeNodeFilter($node->getNode('node'));
|
50 |
}
|
51 |
|
vendor/twig/twig/lib/Twig/Node/Set.php
CHANGED
@@ -9,12 +9,18 @@
|
|
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
|
18 |
{
|
19 |
public function __construct($capture, Twig_NodeInterface $names, Twig_NodeInterface $values, $lineno, $tag = null)
|
20 |
{
|
@@ -23,24 +29,24 @@ class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface
|
|
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
|
27 |
*/
|
28 |
if ($this->getAttribute('capture')) {
|
29 |
$this->setAttribute('safe', true);
|
30 |
|
31 |
$values = $this->getNode('values');
|
32 |
-
if ($values instanceof
|
33 |
-
$this->setNode('values', new
|
34 |
$this->setAttribute('capture', false);
|
35 |
}
|
36 |
}
|
37 |
}
|
38 |
|
39 |
-
public function compile(
|
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) {
|
@@ -61,14 +67,14 @@ class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface
|
|
61 |
$compiler->subcompile($this->getNode('names'), false);
|
62 |
|
63 |
if ($this->getAttribute('capture')) {
|
64 |
-
$compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new
|
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) {
|
@@ -83,7 +89,7 @@ class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface
|
|
83 |
$compiler
|
84 |
->raw("('' === \$tmp = ")
|
85 |
->subcompile($this->getNode('values'))
|
86 |
-
->raw(") ? '' : new
|
87 |
;
|
88 |
} else {
|
89 |
$compiler->subcompile($this->getNode('values'));
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Expression\ConstantExpression;
|
14 |
+
use Twig\Node\Node;
|
15 |
+
use Twig\Node\NodeCaptureInterface;
|
16 |
+
use Twig\Node\TextNode;
|
17 |
+
|
18 |
/**
|
19 |
* Represents a set node.
|
20 |
*
|
21 |
* @author Fabien Potencier <fabien@symfony.com>
|
22 |
*/
|
23 |
+
class Twig_Node_Set extends Node implements NodeCaptureInterface
|
24 |
{
|
25 |
public function __construct($capture, Twig_NodeInterface $names, Twig_NodeInterface $values, $lineno, $tag = null)
|
26 |
{
|
29 |
/*
|
30 |
* Optimizes the node when capture is used for a large block of text.
|
31 |
*
|
32 |
+
* {% set foo %}foo{% endset %} is compiled to $context['foo'] = new Twig\Markup("foo");
|
33 |
*/
|
34 |
if ($this->getAttribute('capture')) {
|
35 |
$this->setAttribute('safe', true);
|
36 |
|
37 |
$values = $this->getNode('values');
|
38 |
+
if ($values instanceof TextNode) {
|
39 |
+
$this->setNode('values', new ConstantExpression($values->getAttribute('data'), $values->getTemplateLine()));
|
40 |
$this->setAttribute('capture', false);
|
41 |
}
|
42 |
}
|
43 |
}
|
44 |
|
45 |
+
public function compile(Compiler $compiler)
|
46 |
{
|
47 |
$compiler->addDebugInfo($this);
|
48 |
|
49 |
+
if (\count($this->getNode('names')) > 1) {
|
50 |
$compiler->write('list(');
|
51 |
foreach ($this->getNode('names') as $idx => $node) {
|
52 |
if ($idx) {
|
67 |
$compiler->subcompile($this->getNode('names'), false);
|
68 |
|
69 |
if ($this->getAttribute('capture')) {
|
70 |
+
$compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new Markup(\$tmp, \$this->env->getCharset())");
|
71 |
}
|
72 |
}
|
73 |
|
74 |
if (!$this->getAttribute('capture')) {
|
75 |
$compiler->raw(' = ');
|
76 |
|
77 |
+
if (\count($this->getNode('names')) > 1) {
|
78 |
$compiler->write('[');
|
79 |
foreach ($this->getNode('values') as $idx => $value) {
|
80 |
if ($idx) {
|
89 |
$compiler
|
90 |
->raw("('' === \$tmp = ")
|
91 |
->subcompile($this->getNode('values'))
|
92 |
+
->raw(") ? '' : new Markup(\$tmp, \$this->env->getCharset())")
|
93 |
;
|
94 |
} else {
|
95 |
$compiler->subcompile($this->getNode('values'));
|
vendor/twig/twig/lib/Twig/Node/SetTemp.php
CHANGED
@@ -9,17 +9,20 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
12 |
/**
|
13 |
* @internal
|
14 |
*/
|
15 |
-
class Twig_Node_SetTemp extends
|
16 |
{
|
17 |
public function __construct($name, $lineno)
|
18 |
{
|
19 |
parent::__construct([], ['name' => $name], $lineno);
|
20 |
}
|
21 |
|
22 |
-
public function compile(
|
23 |
{
|
24 |
$name = $this->getAttribute('name');
|
25 |
$compiler
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Node;
|
14 |
+
|
15 |
/**
|
16 |
* @internal
|
17 |
*/
|
18 |
+
class Twig_Node_SetTemp extends Node
|
19 |
{
|
20 |
public function __construct($name, $lineno)
|
21 |
{
|
22 |
parent::__construct([], ['name' => $name], $lineno);
|
23 |
}
|
24 |
|
25 |
+
public function compile(Compiler $compiler)
|
26 |
{
|
27 |
$name = $this->getAttribute('name');
|
28 |
$compiler
|
vendor/twig/twig/lib/Twig/Node/Spaceless.php
CHANGED
@@ -9,6 +9,9 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Represents a spaceless node.
|
14 |
*
|
@@ -16,14 +19,14 @@
|
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
-
class Twig_Node_Spaceless extends
|
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(
|
27 |
{
|
28 |
$compiler
|
29 |
->addDebugInfo($this)
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Node;
|
14 |
+
|
15 |
/**
|
16 |
* Represents a spaceless node.
|
17 |
*
|
19 |
*
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
+
class Twig_Node_Spaceless extends Node
|
23 |
{
|
24 |
public function __construct(Twig_NodeInterface $body, $lineno, $tag = 'spaceless')
|
25 |
{
|
26 |
parent::__construct(['body' => $body], [], $lineno, $tag);
|
27 |
}
|
28 |
|
29 |
+
public function compile(Compiler $compiler)
|
30 |
{
|
31 |
$compiler
|
32 |
->addDebugInfo($this)
|
vendor/twig/twig/lib/Twig/Node/Text.php
CHANGED
@@ -10,19 +10,23 @@
|
|
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
|
19 |
{
|
20 |
public function __construct($data, $lineno)
|
21 |
{
|
22 |
parent::__construct([], ['data' => $data], $lineno);
|
23 |
}
|
24 |
|
25 |
-
public function compile(
|
26 |
{
|
27 |
$compiler
|
28 |
->addDebugInfo($this)
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Node\Node;
|
15 |
+
use Twig\Node\NodeOutputInterface;
|
16 |
+
|
17 |
/**
|
18 |
* Represents a text node.
|
19 |
*
|
20 |
* @author Fabien Potencier <fabien@symfony.com>
|
21 |
*/
|
22 |
+
class Twig_Node_Text extends Node implements NodeOutputInterface
|
23 |
{
|
24 |
public function __construct($data, $lineno)
|
25 |
{
|
26 |
parent::__construct([], ['data' => $data], $lineno);
|
27 |
}
|
28 |
|
29 |
+
public function compile(Compiler $compiler)
|
30 |
{
|
31 |
$compiler
|
32 |
->addDebugInfo($this)
|
vendor/twig/twig/lib/Twig/Node/With.php
CHANGED
@@ -9,14 +9,17 @@
|
|
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
|
18 |
{
|
19 |
-
public function __construct(
|
20 |
{
|
21 |
$nodes = ['body' => $body];
|
22 |
if (null !== $variables) {
|
@@ -26,7 +29,7 @@ class Twig_Node_With extends Twig_Node
|
|
26 |
parent::__construct($nodes, ['only' => (bool) $only], $lineno, $tag);
|
27 |
}
|
28 |
|
29 |
-
public function compile(
|
30 |
{
|
31 |
$compiler->addDebugInfo($this);
|
32 |
|
@@ -38,7 +41,7 @@ class Twig_Node_With extends Twig_Node
|
|
38 |
->raw(";\n")
|
39 |
->write(sprintf("if (!is_array(\$%s)) {\n", $varsName))
|
40 |
->indent()
|
41 |
-
->write("throw new
|
42 |
->outdent()
|
43 |
->write("}\n")
|
44 |
;
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Node;
|
14 |
+
|
15 |
/**
|
16 |
* Represents a nested "with" scope.
|
17 |
*
|
18 |
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
*/
|
20 |
+
class Twig_Node_With extends Node
|
21 |
{
|
22 |
+
public function __construct(Node $body, Node $variables = null, $only = false, $lineno, $tag = null)
|
23 |
{
|
24 |
$nodes = ['body' => $body];
|
25 |
if (null !== $variables) {
|
29 |
parent::__construct($nodes, ['only' => (bool) $only], $lineno, $tag);
|
30 |
}
|
31 |
|
32 |
+
public function compile(Compiler $compiler)
|
33 |
{
|
34 |
$compiler->addDebugInfo($this);
|
35 |
|
41 |
->raw(";\n")
|
42 |
->write(sprintf("if (!is_array(\$%s)) {\n", $varsName))
|
43 |
->indent()
|
44 |
+
->write("throw new RuntimeError('Variables passed to the \"with\" tag must be a hash.');\n")
|
45 |
->outdent()
|
46 |
->write("}\n")
|
47 |
;
|
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(
|
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)
|
vendor/twig/twig/lib/Twig/NodeTraverser.php
CHANGED
@@ -9,6 +9,9 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Twig_NodeTraverser is a node traverser.
|
14 |
*
|
@@ -24,10 +27,9 @@ class Twig_NodeTraverser
|
|
24 |
protected $visitors = [];
|
25 |
|
26 |
/**
|
27 |
-
* @param
|
28 |
-
* @param Twig_NodeVisitorInterface[] $visitors
|
29 |
*/
|
30 |
-
public function __construct(
|
31 |
{
|
32 |
$this->env = $env;
|
33 |
foreach ($visitors as $visitor) {
|
@@ -35,7 +37,7 @@ class Twig_NodeTraverser
|
|
35 |
}
|
36 |
}
|
37 |
|
38 |
-
public function addVisitor(
|
39 |
{
|
40 |
if (!isset($this->visitors[$visitor->getPriority()])) {
|
41 |
$this->visitors[$visitor->getPriority()] = [];
|
@@ -61,7 +63,7 @@ class Twig_NodeTraverser
|
|
61 |
return $node;
|
62 |
}
|
63 |
|
64 |
-
protected function traverseForVisitor(
|
65 |
{
|
66 |
if (null === $node) {
|
67 |
return;
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Environment;
|
13 |
+
use Twig\NodeVisitor\NodeVisitorInterface;
|
14 |
+
|
15 |
/**
|
16 |
* Twig_NodeTraverser is a node traverser.
|
17 |
*
|
27 |
protected $visitors = [];
|
28 |
|
29 |
/**
|
30 |
+
* @param NodeVisitorInterface[] $visitors
|
|
|
31 |
*/
|
32 |
+
public function __construct(Environment $env, array $visitors = [])
|
33 |
{
|
34 |
$this->env = $env;
|
35 |
foreach ($visitors as $visitor) {
|
37 |
}
|
38 |
}
|
39 |
|
40 |
+
public function addVisitor(NodeVisitorInterface $visitor)
|
41 |
{
|
42 |
if (!isset($this->visitors[$visitor->getPriority()])) {
|
43 |
$this->visitors[$visitor->getPriority()] = [];
|
63 |
return $node;
|
64 |
}
|
65 |
|
66 |
+
protected function traverseForVisitor(NodeVisitorInterface $visitor, Twig_NodeInterface $node = null)
|
67 |
{
|
68 |
if (null === $node) {
|
69 |
return;
|
vendor/twig/twig/lib/Twig/NodeVisitor/Escaper.php
CHANGED
@@ -9,6 +9,20 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Twig_NodeVisitor_Escaper implements output escaping.
|
14 |
*
|
@@ -16,7 +30,7 @@
|
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
-
class Twig_NodeVisitor_Escaper extends
|
20 |
{
|
21 |
protected $statusStack = [];
|
22 |
protected $blocks = [];
|
@@ -27,50 +41,50 @@ class Twig_NodeVisitor_Escaper extends Twig_BaseNodeVisitor
|
|
27 |
|
28 |
public function __construct()
|
29 |
{
|
30 |
-
$this->safeAnalysis = new
|
31 |
}
|
32 |
|
33 |
-
protected function doEnterNode(
|
34 |
{
|
35 |
-
if ($node instanceof
|
36 |
-
if ($env->hasExtension('
|
37 |
$this->defaultStrategy = $defaultStrategy;
|
38 |
}
|
39 |
$this->safeVars = [];
|
40 |
$this->blocks = [];
|
41 |
-
} elseif ($node instanceof
|
42 |
$this->statusStack[] = $node->getAttribute('value');
|
43 |
-
} elseif ($node instanceof
|
44 |
$this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env);
|
45 |
-
} elseif ($node instanceof
|
46 |
$this->safeVars[] = $node->getNode('var')->getAttribute('name');
|
47 |
}
|
48 |
|
49 |
return $node;
|
50 |
}
|
51 |
|
52 |
-
protected function doLeaveNode(
|
53 |
{
|
54 |
-
if ($node instanceof
|
55 |
$this->defaultStrategy = false;
|
56 |
$this->safeVars = [];
|
57 |
$this->blocks = [];
|
58 |
-
} elseif ($node instanceof
|
59 |
return $this->preEscapeFilterNode($node, $env);
|
60 |
-
} elseif ($node instanceof
|
61 |
return $this->escapePrintNode($node, $env, $this->needEscaping($env));
|
62 |
}
|
63 |
|
64 |
-
if ($node instanceof
|
65 |
array_pop($this->statusStack);
|
66 |
-
} elseif ($node instanceof
|
67 |
$this->blocks[$node->getAttribute('name')] = $this->needEscaping($env);
|
68 |
}
|
69 |
|
70 |
return $node;
|
71 |
}
|
72 |
|
73 |
-
protected function escapePrintNode(
|
74 |
{
|
75 |
if (false === $type) {
|
76 |
return $node;
|
@@ -82,7 +96,7 @@ class Twig_NodeVisitor_Escaper extends Twig_BaseNodeVisitor
|
|
82 |
return $node;
|
83 |
}
|
84 |
|
85 |
-
$class = get_class($node);
|
86 |
|
87 |
return new $class(
|
88 |
$this->getEscaperFilter($type, $expression),
|
@@ -90,7 +104,7 @@ class Twig_NodeVisitor_Escaper extends Twig_BaseNodeVisitor
|
|
90 |
);
|
91 |
}
|
92 |
|
93 |
-
protected function preEscapeFilterNode(
|
94 |
{
|
95 |
$name = $filter->getNode('filter')->getAttribute('value');
|
96 |
|
@@ -115,7 +129,7 @@ class Twig_NodeVisitor_Escaper extends Twig_BaseNodeVisitor
|
|
115 |
|
116 |
if (null === $safe) {
|
117 |
if (null === $this->traverser) {
|
118 |
-
$this->traverser = new
|
119 |
}
|
120 |
|
121 |
$this->safeAnalysis->setSafeVars($this->safeVars);
|
@@ -124,13 +138,13 @@ class Twig_NodeVisitor_Escaper extends Twig_BaseNodeVisitor
|
|
124 |
$safe = $this->safeAnalysis->getSafe($expression);
|
125 |
}
|
126 |
|
127 |
-
return in_array($type, $safe) || in_array('all', $safe);
|
128 |
}
|
129 |
|
130 |
-
protected function needEscaping(
|
131 |
{
|
132 |
-
if (count($this->statusStack)) {
|
133 |
-
return $this->statusStack[count($this->statusStack) - 1];
|
134 |
}
|
135 |
|
136 |
return $this->defaultStrategy ? $this->defaultStrategy : false;
|
@@ -139,10 +153,10 @@ class Twig_NodeVisitor_Escaper extends Twig_BaseNodeVisitor
|
|
139 |
protected function getEscaperFilter($type, Twig_NodeInterface $node)
|
140 |
{
|
141 |
$line = $node->getTemplateLine();
|
142 |
-
$name = new
|
143 |
-
$args = new
|
144 |
|
145 |
-
return new
|
146 |
}
|
147 |
|
148 |
public function getPriority()
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Environment;
|
13 |
+
use Twig\Node\AutoEscapeNode;
|
14 |
+
use Twig\Node\BlockNode;
|
15 |
+
use Twig\Node\BlockReferenceNode;
|
16 |
+
use Twig\Node\Expression\ConstantExpression;
|
17 |
+
use Twig\Node\Expression\FilterExpression;
|
18 |
+
use Twig\Node\ImportNode;
|
19 |
+
use Twig\Node\ModuleNode;
|
20 |
+
use Twig\Node\Node;
|
21 |
+
use Twig\Node\PrintNode;
|
22 |
+
use Twig\NodeTraverser;
|
23 |
+
use Twig\NodeVisitor\AbstractNodeVisitor;
|
24 |
+
use Twig\NodeVisitor\SafeAnalysisNodeVisitor;
|
25 |
+
|
26 |
/**
|
27 |
* Twig_NodeVisitor_Escaper implements output escaping.
|
28 |
*
|
30 |
*
|
31 |
* @author Fabien Potencier <fabien@symfony.com>
|
32 |
*/
|
33 |
+
class Twig_NodeVisitor_Escaper extends AbstractNodeVisitor
|
34 |
{
|
35 |
protected $statusStack = [];
|
36 |
protected $blocks = [];
|
41 |
|
42 |
public function __construct()
|
43 |
{
|
44 |
+
$this->safeAnalysis = new SafeAnalysisNodeVisitor();
|
45 |
}
|
46 |
|
47 |
+
protected function doEnterNode(Node $node, Environment $env)
|
48 |
{
|
49 |
+
if ($node instanceof ModuleNode) {
|
50 |
+
if ($env->hasExtension('\Twig\Extension\EscaperExtension') && $defaultStrategy = $env->getExtension('\Twig\Extension\EscaperExtension')->getDefaultStrategy($node->getTemplateName())) {
|
51 |
$this->defaultStrategy = $defaultStrategy;
|
52 |
}
|
53 |
$this->safeVars = [];
|
54 |
$this->blocks = [];
|
55 |
+
} elseif ($node instanceof AutoEscapeNode) {
|
56 |
$this->statusStack[] = $node->getAttribute('value');
|
57 |
+
} elseif ($node instanceof BlockNode) {
|
58 |
$this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env);
|
59 |
+
} elseif ($node instanceof ImportNode) {
|
60 |
$this->safeVars[] = $node->getNode('var')->getAttribute('name');
|
61 |
}
|
62 |
|
63 |
return $node;
|
64 |
}
|
65 |
|
66 |
+
protected function doLeaveNode(Node $node, Environment $env)
|
67 |
{
|
68 |
+
if ($node instanceof ModuleNode) {
|
69 |
$this->defaultStrategy = false;
|
70 |
$this->safeVars = [];
|
71 |
$this->blocks = [];
|
72 |
+
} elseif ($node instanceof FilterExpression) {
|
73 |
return $this->preEscapeFilterNode($node, $env);
|
74 |
+
} elseif ($node instanceof PrintNode) {
|
75 |
return $this->escapePrintNode($node, $env, $this->needEscaping($env));
|
76 |
}
|
77 |
|
78 |
+
if ($node instanceof AutoEscapeNode || $node instanceof BlockNode) {
|
79 |
array_pop($this->statusStack);
|
80 |
+
} elseif ($node instanceof BlockReferenceNode) {
|
81 |
$this->blocks[$node->getAttribute('name')] = $this->needEscaping($env);
|
82 |
}
|
83 |
|
84 |
return $node;
|
85 |
}
|
86 |
|
87 |
+
protected function escapePrintNode(PrintNode $node, Environment $env, $type)
|
88 |
{
|
89 |
if (false === $type) {
|
90 |
return $node;
|
96 |
return $node;
|
97 |
}
|
98 |
|
99 |
+
$class = \get_class($node);
|
100 |
|
101 |
return new $class(
|
102 |
$this->getEscaperFilter($type, $expression),
|
104 |
);
|
105 |
}
|
106 |
|
107 |
+
protected function preEscapeFilterNode(FilterExpression $filter, Environment $env)
|
108 |
{
|
109 |
$name = $filter->getNode('filter')->getAttribute('value');
|
110 |
|
129 |
|
130 |
if (null === $safe) {
|
131 |
if (null === $this->traverser) {
|
132 |
+
$this->traverser = new NodeTraverser($env, [$this->safeAnalysis]);
|
133 |
}
|
134 |
|
135 |
$this->safeAnalysis->setSafeVars($this->safeVars);
|
138 |
$safe = $this->safeAnalysis->getSafe($expression);
|
139 |
}
|
140 |
|
141 |
+
return \in_array($type, $safe) || \in_array('all', $safe);
|
142 |
}
|
143 |
|
144 |
+
protected function needEscaping(Environment $env)
|
145 |
{
|
146 |
+
if (\count($this->statusStack)) {
|
147 |
+
return $this->statusStack[\count($this->statusStack) - 1];
|
148 |
}
|
149 |
|
150 |
return $this->defaultStrategy ? $this->defaultStrategy : false;
|
153 |
protected function getEscaperFilter($type, Twig_NodeInterface $node)
|
154 |
{
|
155 |
$line = $node->getTemplateLine();
|
156 |
+
$name = new ConstantExpression('escape', $line);
|
157 |
+
$args = new Node([new ConstantExpression((string) $type, $line), new ConstantExpression(null, $line), new ConstantExpression(true, $line)]);
|
158 |
|
159 |
+
return new FilterExpression($node, $name, $args, $line);
|
160 |
}
|
161 |
|
162 |
public function getPriority()
|
vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php
CHANGED
@@ -9,6 +9,25 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Twig_NodeVisitor_Optimizer tries to optimizes the AST.
|
14 |
*
|
@@ -21,7 +40,7 @@
|
|
21 |
*
|
22 |
* @author Fabien Potencier <fabien@symfony.com>
|
23 |
*/
|
24 |
-
class Twig_NodeVisitor_Optimizer extends
|
25 |
{
|
26 |
const OPTIMIZE_ALL = -1;
|
27 |
const OPTIMIZE_NONE = 0;
|
@@ -40,29 +59,29 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
40 |
*/
|
41 |
public function __construct($optimizers = -1)
|
42 |
{
|
43 |
-
if (
|
44 |
-
throw new InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers));
|
45 |
}
|
46 |
|
47 |
$this->optimizers = $optimizers;
|
48 |
}
|
49 |
|
50 |
-
protected function doEnterNode(
|
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('
|
57 |
if ($this->inABody) {
|
58 |
-
if (!$node instanceof
|
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
|
66 |
$this->inABody = true;
|
67 |
}
|
68 |
}
|
@@ -70,9 +89,9 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
70 |
return $node;
|
71 |
}
|
72 |
|
73 |
-
protected function doLeaveNode(
|
74 |
{
|
75 |
-
$expression = $node instanceof
|
76 |
|
77 |
if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
|
78 |
$this->leaveOptimizeFor($node, $env);
|
@@ -84,18 +103,18 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
84 |
|
85 |
$node = $this->optimizePrintNode($node, $env);
|
86 |
|
87 |
-
if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('
|
88 |
-
if ($node instanceof
|
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
|
95 |
}
|
96 |
|
97 |
$nodes[] = $node;
|
98 |
-
$node = new
|
99 |
}
|
100 |
}
|
101 |
}
|
@@ -103,12 +122,12 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
103 |
return $node;
|
104 |
}
|
105 |
|
106 |
-
protected function optimizeVariables(Twig_NodeInterface $node,
|
107 |
{
|
108 |
-
if ('Twig_Node_Expression_Name' === get_class($node) && $node->isSimple()) {
|
109 |
$this->prependedNodes[0][] = $node->getAttribute('name');
|
110 |
|
111 |
-
return new
|
112 |
}
|
113 |
|
114 |
return $node;
|
@@ -123,16 +142,16 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
123 |
*
|
124 |
* @return Twig_NodeInterface
|
125 |
*/
|
126 |
-
protected function optimizePrintNode(Twig_NodeInterface $node,
|
127 |
{
|
128 |
-
if (!$node instanceof
|
129 |
return $node;
|
130 |
}
|
131 |
|
132 |
$exprNode = $node->getNode('expr');
|
133 |
if (
|
134 |
-
$exprNode instanceof
|
135 |
-
$exprNode instanceof
|
136 |
) {
|
137 |
$exprNode->setAttribute('output', true);
|
138 |
|
@@ -147,9 +166,9 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
147 |
*
|
148 |
* @return Twig_NodeInterface
|
149 |
*/
|
150 |
-
protected function optimizeRawFilter(Twig_NodeInterface $node,
|
151 |
{
|
152 |
-
if ($node instanceof
|
153 |
return $node->getNode('node');
|
154 |
}
|
155 |
|
@@ -159,9 +178,9 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
159 |
/**
|
160 |
* Optimizes "for" tag by removing the "loop" variable creation whenever possible.
|
161 |
*/
|
162 |
-
protected function enterOptimizeFor(Twig_NodeInterface $node,
|
163 |
{
|
164 |
-
if ($node instanceof
|
165 |
// disable the loop variable by default
|
166 |
$node->setAttribute('with_loop', false);
|
167 |
array_unshift($this->loops, $node);
|
@@ -175,28 +194,28 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
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
|
179 |
$node->setAttribute('always_defined', true);
|
180 |
$this->addLoopToCurrent();
|
181 |
}
|
182 |
|
183 |
// optimize access to loop targets
|
184 |
-
elseif ($node instanceof
|
185 |
$node->setAttribute('always_defined', true);
|
186 |
}
|
187 |
|
188 |
// block reference
|
189 |
-
elseif ($node instanceof
|
190 |
$this->addLoopToCurrent();
|
191 |
}
|
192 |
|
193 |
// include without the only attribute
|
194 |
-
elseif ($node instanceof
|
195 |
$this->addLoopToAll();
|
196 |
}
|
197 |
|
198 |
// include function without the with_context=false parameter
|
199 |
-
elseif ($node instanceof
|
200 |
&& 'include' === $node->getAttribute('name')
|
201 |
&& (!$node->getNode('arguments')->hasNode('with_context')
|
202 |
|| false !== $node->getNode('arguments')->getNode('with_context')->getAttribute('value')
|
@@ -206,12 +225,12 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
206 |
}
|
207 |
|
208 |
// the loop variable is referenced via an attribute
|
209 |
-
elseif ($node instanceof
|
210 |
-
&& (!$node->getNode('attribute') instanceof
|
211 |
|| 'parent' === $node->getNode('attribute')->getAttribute('value')
|
212 |
)
|
213 |
&& (true === $this->loops[0]->getAttribute('with_loop')
|
214 |
-
|| ($node->getNode('node') instanceof
|
215 |
&& 'loop' === $node->getNode('node')->getAttribute('name')
|
216 |
)
|
217 |
)
|
@@ -223,9 +242,9 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
|
223 |
/**
|
224 |
* Optimizes "for" tag by removing the "loop" variable creation whenever possible.
|
225 |
*/
|
226 |
-
protected function leaveOptimizeFor(Twig_NodeInterface $node,
|
227 |
{
|
228 |
-
if ($node instanceof
|
229 |
array_shift($this->loops);
|
230 |
array_shift($this->loopsTargets);
|
231 |
array_shift($this->loopsTargets);
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Environment;
|
13 |
+
use Twig\Node\BlockReferenceNode;
|
14 |
+
use Twig\Node\BodyNode;
|
15 |
+
use Twig\Node\Expression\AbstractExpression;
|
16 |
+
use Twig\Node\Expression\BlockReferenceExpression;
|
17 |
+
use Twig\Node\Expression\ConstantExpression;
|
18 |
+
use Twig\Node\Expression\FilterExpression;
|
19 |
+
use Twig\Node\Expression\FunctionExpression;
|
20 |
+
use Twig\Node\Expression\GetAttrExpression;
|
21 |
+
use Twig\Node\Expression\NameExpression;
|
22 |
+
use Twig\Node\Expression\ParentExpression;
|
23 |
+
use Twig\Node\Expression\TempNameExpression;
|
24 |
+
use Twig\Node\ForNode;
|
25 |
+
use Twig\Node\IncludeNode;
|
26 |
+
use Twig\Node\Node;
|
27 |
+
use Twig\Node\PrintNode;
|
28 |
+
use Twig\Node\SetTempNode;
|
29 |
+
use Twig\NodeVisitor\AbstractNodeVisitor;
|
30 |
+
|
31 |
/**
|
32 |
* Twig_NodeVisitor_Optimizer tries to optimizes the AST.
|
33 |
*
|
40 |
*
|
41 |
* @author Fabien Potencier <fabien@symfony.com>
|
42 |
*/
|
43 |
+
class Twig_NodeVisitor_Optimizer extends AbstractNodeVisitor
|
44 |
{
|
45 |
const OPTIMIZE_ALL = -1;
|
46 |
const OPTIMIZE_NONE = 0;
|
59 |
*/
|
60 |
public function __construct($optimizers = -1)
|
61 |
{
|
62 |
+
if (!\is_int($optimizers) || $optimizers > (self::OPTIMIZE_FOR | self::OPTIMIZE_RAW_FILTER | self::OPTIMIZE_VAR_ACCESS)) {
|
63 |
+
throw new \InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers));
|
64 |
}
|
65 |
|
66 |
$this->optimizers = $optimizers;
|
67 |
}
|
68 |
|
69 |
+
protected function doEnterNode(Node $node, Environment $env)
|
70 |
{
|
71 |
if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
|
72 |
$this->enterOptimizeFor($node, $env);
|
73 |
}
|
74 |
|
75 |
+
if (PHP_VERSION_ID < 50400 && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('\Twig\Extension\SandboxExtension')) {
|
76 |
if ($this->inABody) {
|
77 |
+
if (!$node instanceof AbstractExpression) {
|
78 |
+
if ('Twig_Node' !== \get_class($node)) {
|
79 |
array_unshift($this->prependedNodes, []);
|
80 |
}
|
81 |
} else {
|
82 |
$node = $this->optimizeVariables($node, $env);
|
83 |
}
|
84 |
+
} elseif ($node instanceof BodyNode) {
|
85 |
$this->inABody = true;
|
86 |
}
|
87 |
}
|
89 |
return $node;
|
90 |
}
|
91 |
|
92 |
+
protected function doLeaveNode(Node $node, Environment $env)
|
93 |
{
|
94 |
+
$expression = $node instanceof AbstractExpression;
|
95 |
|
96 |
if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
|
97 |
$this->leaveOptimizeFor($node, $env);
|
103 |
|
104 |
$node = $this->optimizePrintNode($node, $env);
|
105 |
|
106 |
+
if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('\Twig\Extension\SandboxExtension')) {
|
107 |
+
if ($node instanceof BodyNode) {
|
108 |
$this->inABody = false;
|
109 |
} elseif ($this->inABody) {
|
110 |
+
if (!$expression && 'Twig_Node' !== \get_class($node) && $prependedNodes = array_shift($this->prependedNodes)) {
|
111 |
$nodes = [];
|
112 |
foreach (array_unique($prependedNodes) as $name) {
|
113 |
+
$nodes[] = new SetTempNode($name, $node->getTemplateLine());
|
114 |
}
|
115 |
|
116 |
$nodes[] = $node;
|
117 |
+
$node = new Node($nodes);
|
118 |
}
|
119 |
}
|
120 |
}
|
122 |
return $node;
|
123 |
}
|
124 |
|
125 |
+
protected function optimizeVariables(Twig_NodeInterface $node, Environment $env)
|
126 |
{
|
127 |
+
if ('Twig_Node_Expression_Name' === \get_class($node) && $node->isSimple()) {
|
128 |
$this->prependedNodes[0][] = $node->getAttribute('name');
|
129 |
|
130 |
+
return new TempNameExpression($node->getAttribute('name'), $node->getTemplateLine());
|
131 |
}
|
132 |
|
133 |
return $node;
|
142 |
*
|
143 |
* @return Twig_NodeInterface
|
144 |
*/
|
145 |
+
protected function optimizePrintNode(Twig_NodeInterface $node, Environment $env)
|
146 |
{
|
147 |
+
if (!$node instanceof PrintNode) {
|
148 |
return $node;
|
149 |
}
|
150 |
|
151 |
$exprNode = $node->getNode('expr');
|
152 |
if (
|
153 |
+
$exprNode instanceof BlockReferenceExpression ||
|
154 |
+
$exprNode instanceof ParentExpression
|
155 |
) {
|
156 |
$exprNode->setAttribute('output', true);
|
157 |
|
166 |
*
|
167 |
* @return Twig_NodeInterface
|
168 |
*/
|
169 |
+
protected function optimizeRawFilter(Twig_NodeInterface $node, Environment $env)
|
170 |
{
|
171 |
+
if ($node instanceof FilterExpression && 'raw' == $node->getNode('filter')->getAttribute('value')) {
|
172 |
return $node->getNode('node');
|
173 |
}
|
174 |
|
178 |
/**
|
179 |
* Optimizes "for" tag by removing the "loop" variable creation whenever possible.
|
180 |
*/
|
181 |
+
protected function enterOptimizeFor(Twig_NodeInterface $node, Environment $env)
|
182 |
{
|
183 |
+
if ($node instanceof ForNode) {
|
184 |
// disable the loop variable by default
|
185 |
$node->setAttribute('with_loop', false);
|
186 |
array_unshift($this->loops, $node);
|
194 |
// when do we need to add the loop variable back?
|
195 |
|
196 |
// the loop variable is referenced for the current loop
|
197 |
+
elseif ($node instanceof NameExpression && 'loop' === $node->getAttribute('name')) {
|
198 |
$node->setAttribute('always_defined', true);
|
199 |
$this->addLoopToCurrent();
|
200 |
}
|
201 |
|
202 |
// optimize access to loop targets
|
203 |
+
elseif ($node instanceof NameExpression && \in_array($node->getAttribute('name'), $this->loopsTargets)) {
|
204 |
$node->setAttribute('always_defined', true);
|
205 |
}
|
206 |
|
207 |
// block reference
|
208 |
+
elseif ($node instanceof BlockReferenceNode || $node instanceof BlockReferenceExpression) {
|
209 |
$this->addLoopToCurrent();
|
210 |
}
|
211 |
|
212 |
// include without the only attribute
|
213 |
+
elseif ($node instanceof IncludeNode && !$node->getAttribute('only')) {
|
214 |
$this->addLoopToAll();
|
215 |
}
|
216 |
|
217 |
// include function without the with_context=false parameter
|
218 |
+
elseif ($node instanceof FunctionExpression
|
219 |
&& 'include' === $node->getAttribute('name')
|
220 |
&& (!$node->getNode('arguments')->hasNode('with_context')
|
221 |
|| false !== $node->getNode('arguments')->getNode('with_context')->getAttribute('value')
|
225 |
}
|
226 |
|
227 |
// the loop variable is referenced via an attribute
|
228 |
+
elseif ($node instanceof GetAttrExpression
|
229 |
+
&& (!$node->getNode('attribute') instanceof ConstantExpression
|
230 |
|| 'parent' === $node->getNode('attribute')->getAttribute('value')
|
231 |
)
|
232 |
&& (true === $this->loops[0]->getAttribute('with_loop')
|
233 |
+
|| ($node->getNode('node') instanceof NameExpression
|
234 |
&& 'loop' === $node->getNode('node')->getAttribute('name')
|
235 |
)
|
236 |
)
|
242 |
/**
|
243 |
* Optimizes "for" tag by removing the "loop" variable creation whenever possible.
|
244 |
*/
|
245 |
+
protected function leaveOptimizeFor(Twig_NodeInterface $node, Environment $env)
|
246 |
{
|
247 |
+
if ($node instanceof ForNode) {
|
248 |
array_shift($this->loops);
|
249 |
array_shift($this->loopsTargets);
|
250 |
array_shift($this->loopsTargets);
|
vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php
CHANGED
@@ -9,10 +9,23 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* @final
|
14 |
*/
|
15 |
-
class Twig_NodeVisitor_SafeAnalysis extends
|
16 |
{
|
17 |
protected $data = [];
|
18 |
protected $safeVars = [];
|
@@ -34,7 +47,7 @@ class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor
|
|
34 |
continue;
|
35 |
}
|
36 |
|
37 |
-
if (in_array('html_attr', $bucket['value'])) {
|
38 |
$bucket['value'][] = 'html';
|
39 |
}
|
40 |
|
@@ -60,27 +73,27 @@ class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor
|
|
60 |
];
|
61 |
}
|
62 |
|
63 |
-
protected function doEnterNode(
|
64 |
{
|
65 |
return $node;
|
66 |
}
|
67 |
|
68 |
-
protected function doLeaveNode(
|
69 |
{
|
70 |
-
if ($node instanceof
|
71 |
// constants are marked safe for all
|
72 |
$this->setSafe($node, ['all']);
|
73 |
-
} elseif ($node instanceof
|
74 |
// blocks are safe by definition
|
75 |
$this->setSafe($node, ['all']);
|
76 |
-
} elseif ($node instanceof
|
77 |
// parent block is safe by definition
|
78 |
$this->setSafe($node, ['all']);
|
79 |
-
} elseif ($node instanceof
|
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
|
84 |
// filter expression is safe when the filter is safe
|
85 |
$name = $node->getNode('filter')->getAttribute('value');
|
86 |
$args = $node->getNode('arguments');
|
@@ -93,7 +106,7 @@ class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor
|
|
93 |
} else {
|
94 |
$this->setSafe($node, []);
|
95 |
}
|
96 |
-
} elseif ($node instanceof
|
97 |
// function expression is safe when the function is safe
|
98 |
$name = $node->getAttribute('name');
|
99 |
$args = $node->getNode('arguments');
|
@@ -103,16 +116,16 @@ class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor
|
|
103 |
} else {
|
104 |
$this->setSafe($node, []);
|
105 |
}
|
106 |
-
} elseif ($node instanceof
|
107 |
if ($node->getAttribute('safe')) {
|
108 |
$this->setSafe($node, ['all']);
|
109 |
} else {
|
110 |
$this->setSafe($node, []);
|
111 |
}
|
112 |
-
} elseif ($node instanceof
|
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, []);
|
@@ -130,11 +143,11 @@ class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor
|
|
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 |
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Environment;
|
13 |
+
use Twig\Node\Expression\BlockReferenceExpression;
|
14 |
+
use Twig\Node\Expression\ConditionalExpression;
|
15 |
+
use Twig\Node\Expression\ConstantExpression;
|
16 |
+
use Twig\Node\Expression\FilterExpression;
|
17 |
+
use Twig\Node\Expression\FunctionExpression;
|
18 |
+
use Twig\Node\Expression\GetAttrExpression;
|
19 |
+
use Twig\Node\Expression\MethodCallExpression;
|
20 |
+
use Twig\Node\Expression\NameExpression;
|
21 |
+
use Twig\Node\Expression\ParentExpression;
|
22 |
+
use Twig\Node\Node;
|
23 |
+
use Twig\NodeVisitor\AbstractNodeVisitor;
|
24 |
+
|
25 |
/**
|
26 |
* @final
|
27 |
*/
|
28 |
+
class Twig_NodeVisitor_SafeAnalysis extends AbstractNodeVisitor
|
29 |
{
|
30 |
protected $data = [];
|
31 |
protected $safeVars = [];
|
47 |
continue;
|
48 |
}
|
49 |
|
50 |
+
if (\in_array('html_attr', $bucket['value'])) {
|
51 |
$bucket['value'][] = 'html';
|
52 |
}
|
53 |
|
73 |
];
|
74 |
}
|
75 |
|
76 |
+
protected function doEnterNode(Node $node, Environment $env)
|
77 |
{
|
78 |
return $node;
|
79 |
}
|
80 |
|
81 |
+
protected function doLeaveNode(Node $node, Environment $env)
|
82 |
{
|
83 |
+
if ($node instanceof ConstantExpression) {
|
84 |
// constants are marked safe for all
|
85 |
$this->setSafe($node, ['all']);
|
86 |
+
} elseif ($node instanceof BlockReferenceExpression) {
|
87 |
// blocks are safe by definition
|
88 |
$this->setSafe($node, ['all']);
|
89 |
+
} elseif ($node instanceof ParentExpression) {
|
90 |
// parent block is safe by definition
|
91 |
$this->setSafe($node, ['all']);
|
92 |
+
} elseif ($node instanceof ConditionalExpression) {
|
93 |
// intersect safeness of both operands
|
94 |
$safe = $this->intersectSafe($this->getSafe($node->getNode('expr2')), $this->getSafe($node->getNode('expr3')));
|
95 |
$this->setSafe($node, $safe);
|
96 |
+
} elseif ($node instanceof FilterExpression) {
|
97 |
// filter expression is safe when the filter is safe
|
98 |
$name = $node->getNode('filter')->getAttribute('value');
|
99 |
$args = $node->getNode('arguments');
|
106 |
} else {
|
107 |
$this->setSafe($node, []);
|
108 |
}
|
109 |
+
} elseif ($node instanceof FunctionExpression) {
|
110 |
// function expression is safe when the function is safe
|
111 |
$name = $node->getAttribute('name');
|
112 |
$args = $node->getNode('arguments');
|
116 |
} else {
|
117 |
$this->setSafe($node, []);
|
118 |
}
|
119 |
+
} elseif ($node instanceof MethodCallExpression) {
|
120 |
if ($node->getAttribute('safe')) {
|
121 |
$this->setSafe($node, ['all']);
|
122 |
} else {
|
123 |
$this->setSafe($node, []);
|
124 |
}
|
125 |
+
} elseif ($node instanceof GetAttrExpression && $node->getNode('node') instanceof NameExpression) {
|
126 |
$name = $node->getNode('node')->getAttribute('name');
|
127 |
// attributes on template instances are safe
|
128 |
+
if ('_self' == $name || \in_array($name, $this->safeVars)) {
|
129 |
$this->setSafe($node, ['all']);
|
130 |
} else {
|
131 |
$this->setSafe($node, []);
|
143 |
return [];
|
144 |
}
|
145 |
|
146 |
+
if (\in_array('all', $a)) {
|
147 |
return $b;
|
148 |
}
|
149 |
|
150 |
+
if (\in_array('all', $b)) {
|
151 |
return $a;
|
152 |
}
|
153 |
|
vendor/twig/twig/lib/Twig/NodeVisitor/Sandbox.php
CHANGED
@@ -9,6 +9,17 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Twig_NodeVisitor_Sandbox implements sandboxing.
|
14 |
*
|
@@ -16,16 +27,16 @@
|
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
-
class Twig_NodeVisitor_Sandbox extends
|
20 |
{
|
21 |
protected $inAModule = false;
|
22 |
protected $tags;
|
23 |
protected $filters;
|
24 |
protected $functions;
|
25 |
|
26 |
-
protected function doEnterNode(
|
27 |
{
|
28 |
-
if ($node instanceof
|
29 |
$this->inAModule = true;
|
30 |
$this->tags = [];
|
31 |
$this->filters = [];
|
@@ -39,35 +50,35 @@ class Twig_NodeVisitor_Sandbox extends Twig_BaseNodeVisitor
|
|
39 |
}
|
40 |
|
41 |
// look for filters
|
42 |
-
if ($node instanceof
|
43 |
$this->filters[$node->getNode('filter')->getAttribute('value')] = $node;
|
44 |
}
|
45 |
|
46 |
// look for functions
|
47 |
-
if ($node instanceof
|
48 |
$this->functions[$node->getAttribute('name')] = $node;
|
49 |
}
|
50 |
|
51 |
// the .. operator is equivalent to the range() function
|
52 |
-
if ($node instanceof
|
53 |
$this->functions['range'] = $node;
|
54 |
}
|
55 |
|
56 |
// wrap print to check __toString() calls
|
57 |
-
if ($node instanceof
|
58 |
-
return new
|
59 |
}
|
60 |
}
|
61 |
|
62 |
return $node;
|
63 |
}
|
64 |
|
65 |
-
protected function doLeaveNode(
|
66 |
{
|
67 |
-
if ($node instanceof
|
68 |
$this->inAModule = false;
|
69 |
|
70 |
-
$node->setNode('display_start', new
|
71 |
}
|
72 |
|
73 |
return $node;
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Environment;
|
13 |
+
use Twig\Node\CheckSecurityNode;
|
14 |
+
use Twig\Node\Expression\Binary\RangeBinary;
|
15 |
+
use Twig\Node\Expression\FilterExpression;
|
16 |
+
use Twig\Node\Expression\FunctionExpression;
|
17 |
+
use Twig\Node\ModuleNode;
|
18 |
+
use Twig\Node\Node;
|
19 |
+
use Twig\Node\PrintNode;
|
20 |
+
use Twig\Node\SandboxedPrintNode;
|
21 |
+
use Twig\NodeVisitor\AbstractNodeVisitor;
|
22 |
+
|
23 |
/**
|
24 |
* Twig_NodeVisitor_Sandbox implements sandboxing.
|
25 |
*
|
27 |
*
|
28 |
* @author Fabien Potencier <fabien@symfony.com>
|
29 |
*/
|
30 |
+
class Twig_NodeVisitor_Sandbox extends AbstractNodeVisitor
|
31 |
{
|
32 |
protected $inAModule = false;
|
33 |
protected $tags;
|
34 |
protected $filters;
|
35 |
protected $functions;
|
36 |
|
37 |
+
protected function doEnterNode(Node $node, Environment $env)
|
38 |
{
|
39 |
+
if ($node instanceof ModuleNode) {
|
40 |
$this->inAModule = true;
|
41 |
$this->tags = [];
|
42 |
$this->filters = [];
|
50 |
}
|
51 |
|
52 |
// look for filters
|
53 |
+
if ($node instanceof FilterExpression && !isset($this->filters[$node->getNode('filter')->getAttribute('value')])) {
|
54 |
$this->filters[$node->getNode('filter')->getAttribute('value')] = $node;
|
55 |
}
|
56 |
|
57 |
// look for functions
|
58 |
+
if ($node instanceof FunctionExpression && !isset($this->functions[$node->getAttribute('name')])) {
|
59 |
$this->functions[$node->getAttribute('name')] = $node;
|
60 |
}
|
61 |
|
62 |
// the .. operator is equivalent to the range() function
|
63 |
+
if ($node instanceof RangeBinary && !isset($this->functions['range'])) {
|
64 |
$this->functions['range'] = $node;
|
65 |
}
|
66 |
|
67 |
// wrap print to check __toString() calls
|
68 |
+
if ($node instanceof PrintNode) {
|
69 |
+
return new SandboxedPrintNode($node->getNode('expr'), $node->getTemplateLine(), $node->getNodeTag());
|
70 |
}
|
71 |
}
|
72 |
|
73 |
return $node;
|
74 |
}
|
75 |
|
76 |
+
protected function doLeaveNode(Node $node, Environment $env)
|
77 |
{
|
78 |
+
if ($node instanceof ModuleNode) {
|
79 |
$this->inAModule = false;
|
80 |
|
81 |
+
$node->setNode('display_start', new Node([new CheckSecurityNode($this->filters, $this->tags, $this->functions), $node->getNode('display_start')]));
|
82 |
}
|
83 |
|
84 |
return $node;
|
vendor/twig/twig/lib/Twig/NodeVisitorInterface.php
CHANGED
@@ -9,6 +9,8 @@
|
|
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 |
*
|
@@ -21,14 +23,14 @@ interface Twig_NodeVisitorInterface
|
|
21 |
*
|
22 |
* @return Twig_NodeInterface The modified node
|
23 |
*/
|
24 |
-
public function enterNode(Twig_NodeInterface $node,
|
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,
|
32 |
|
33 |
/**
|
34 |
* Returns the priority for this visitor.
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Environment;
|
13 |
+
|
14 |
/**
|
15 |
* Twig_NodeVisitorInterface is the interface the all node visitor classes must implement.
|
16 |
*
|
23 |
*
|
24 |
* @return Twig_NodeInterface The modified node
|
25 |
*/
|
26 |
+
public function enterNode(Twig_NodeInterface $node, Environment $env);
|
27 |
|
28 |
/**
|
29 |
* Called after child nodes are visited.
|
30 |
*
|
31 |
* @return Twig_NodeInterface|false The modified node or false if the node must be removed
|
32 |
*/
|
33 |
+
public function leaveNode(Twig_NodeInterface $node, Environment $env);
|
34 |
|
35 |
/**
|
36 |
* Returns the priority for this visitor.
|
vendor/twig/twig/lib/Twig/Parser.php
CHANGED
@@ -10,6 +10,26 @@
|
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
/**
|
14 |
* Default parser implementation.
|
15 |
*
|
@@ -33,7 +53,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
33 |
protected $embeddedTemplates = [];
|
34 |
private $varNameSalt = 0;
|
35 |
|
36 |
-
public function __construct(
|
37 |
{
|
38 |
$this->env = $env;
|
39 |
}
|
@@ -63,7 +83,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
63 |
return $this->stream->getSourceContext()->getName();
|
64 |
}
|
65 |
|
66 |
-
public function parse(
|
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
|
@@ -88,7 +108,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
88 |
}
|
89 |
|
90 |
if (null === $this->expressionParser) {
|
91 |
-
$this->expressionParser = new
|
92 |
}
|
93 |
|
94 |
$this->stream = $stream;
|
@@ -105,9 +125,9 @@ class Twig_Parser implements Twig_ParserInterface
|
|
105 |
$body = $this->subparse($test, $dropNeedle);
|
106 |
|
107 |
if (null !== $this->parent && null === $body = $this->filterBodyNodes($body)) {
|
108 |
-
$body = new
|
109 |
}
|
110 |
-
} catch (
|
111 |
if (!$e->getSourceContext()) {
|
112 |
$e->setSourceContext($this->stream->getSourceContext());
|
113 |
}
|
@@ -119,9 +139,9 @@ class Twig_Parser implements Twig_ParserInterface
|
|
119 |
throw $e;
|
120 |
}
|
121 |
|
122 |
-
$node = new
|
123 |
|
124 |
-
$traverser = new
|
125 |
|
126 |
$node = $traverser->traverse($node);
|
127 |
|
@@ -139,48 +159,48 @@ class Twig_Parser implements Twig_ParserInterface
|
|
139 |
$rv = [];
|
140 |
while (!$this->stream->isEOF()) {
|
141 |
switch ($this->getCurrentToken()->getType()) {
|
142 |
-
case
|
143 |
$token = $this->stream->next();
|
144 |
-
$rv[] = new
|
145 |
break;
|
146 |
|
147 |
-
case
|
148 |
$token = $this->stream->next();
|
149 |
$expr = $this->expressionParser->parseExpression();
|
150 |
-
$this->stream->expect(
|
151 |
-
$rv[] = new
|
152 |
break;
|
153 |
|
154 |
-
case
|
155 |
$this->stream->next();
|
156 |
$token = $this->getCurrentToken();
|
157 |
|
158 |
-
if (
|
159 |
-
throw new
|
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
|
172 |
}
|
173 |
|
174 |
$subparser = $this->handlers->getTokenParser($token->getValue());
|
175 |
if (null === $subparser) {
|
176 |
if (null !== $test) {
|
177 |
-
$e = new
|
178 |
|
179 |
-
if (is_array($test) && isset($test[0]) && $test[0] instanceof
|
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
|
184 |
$e->addSuggestions($token->getValue(), array_keys($this->env->getTags()));
|
185 |
}
|
186 |
|
@@ -196,15 +216,15 @@ class Twig_Parser implements Twig_ParserInterface
|
|
196 |
break;
|
197 |
|
198 |
default:
|
199 |
-
throw new
|
200 |
}
|
201 |
}
|
202 |
|
203 |
-
if (1 === count($rv)) {
|
204 |
return $rv[0];
|
205 |
}
|
206 |
|
207 |
-
return new
|
208 |
}
|
209 |
|
210 |
/**
|
@@ -220,7 +240,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
220 |
/**
|
221 |
* @deprecated since 1.27 (to be removed in 2.0)
|
222 |
*/
|
223 |
-
public function addNodeVisitor(
|
224 |
{
|
225 |
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0.', E_USER_DEPRECATED);
|
226 |
|
@@ -234,7 +254,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
234 |
|
235 |
public function peekBlockStack()
|
236 |
{
|
237 |
-
return $this->blockStack[count($this->blockStack) - 1];
|
238 |
}
|
239 |
|
240 |
public function popBlockStack()
|
@@ -257,9 +277,9 @@ class Twig_Parser implements Twig_ParserInterface
|
|
257 |
return $this->blocks[$name];
|
258 |
}
|
259 |
|
260 |
-
public function setBlock($name,
|
261 |
{
|
262 |
-
$this->blocks[$name] = new
|
263 |
}
|
264 |
|
265 |
public function hasMacro($name)
|
@@ -267,10 +287,10 @@ class Twig_Parser implements Twig_ParserInterface
|
|
267 |
return isset($this->macros[$name]);
|
268 |
}
|
269 |
|
270 |
-
public function setMacro($name,
|
271 |
{
|
272 |
if ($this->isReservedMacroName($name)) {
|
273 |
-
throw new
|
274 |
}
|
275 |
|
276 |
$this->macros[$name] = $node;
|
@@ -280,7 +300,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
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 |
|
@@ -290,7 +310,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
290 |
}
|
291 |
}
|
292 |
|
293 |
-
return in_array(strtolower($name), $this->reservedMacroNames);
|
294 |
}
|
295 |
|
296 |
public function addTrait($trait)
|
@@ -300,17 +320,17 @@ class Twig_Parser implements Twig_ParserInterface
|
|
300 |
|
301 |
public function hasTraits()
|
302 |
{
|
303 |
-
return count($this->traits) > 0;
|
304 |
}
|
305 |
|
306 |
-
public function embedTemplate(
|
307 |
{
|
308 |
$template->setIndex(mt_rand());
|
309 |
|
310 |
$this->embeddedTemplates[] = $template;
|
311 |
}
|
312 |
|
313 |
-
public function addImportedSymbol($type, $alias, $name = null,
|
314 |
{
|
315 |
$this->importedSymbols[0][$type][$alias] = ['name' => $name, 'node' => $node];
|
316 |
}
|
@@ -326,7 +346,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
326 |
|
327 |
public function isMainScope()
|
328 |
{
|
329 |
-
return 1 === count($this->importedSymbols);
|
330 |
}
|
331 |
|
332 |
public function pushLocalScope()
|
@@ -340,7 +360,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
340 |
}
|
341 |
|
342 |
/**
|
343 |
-
* @return
|
344 |
*/
|
345 |
public function getExpressionParser()
|
346 |
{
|
@@ -358,7 +378,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
358 |
}
|
359 |
|
360 |
/**
|
361 |
-
* @return
|
362 |
*/
|
363 |
public function getStream()
|
364 |
{
|
@@ -366,7 +386,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|
366 |
}
|
367 |
|
368 |
/**
|
369 |
-
* @return
|
370 |
*/
|
371 |
public function getCurrentToken()
|
372 |
{
|
@@ -377,11 +397,11 @@ class Twig_Parser implements Twig_ParserInterface
|
|
377 |
{
|
378 |
// check that the body does not contain non-empty output nodes
|
379 |
if (
|
380 |
-
($node instanceof
|
381 |
||
|
382 |
-
(!$node instanceof
|
383 |
) {
|
384 |
-
if (false !== strpos((string) $node, chr(0xEF)
|
385 |
$t = substr($node->getAttribute('data'), 3);
|
386 |
if ('' === $t || ctype_space($t)) {
|
387 |
// bypass empty nodes starting with a BOM
|
@@ -389,15 +409,15 @@ class Twig_Parser implements Twig_ParserInterface
|
|
389 |
}
|
390 |
}
|
391 |
|
392 |
-
throw new
|
393 |
}
|
394 |
|
395 |
// bypass nodes that will "capture" the output
|
396 |
-
if ($node instanceof
|
397 |
return $node;
|
398 |
}
|
399 |
|
400 |
-
if ($node instanceof
|
401 |
return;
|
402 |
}
|
403 |
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Environment;
|
14 |
+
use Twig\Error\SyntaxError;
|
15 |
+
use Twig\ExpressionParser;
|
16 |
+
use Twig\Node\BlockNode;
|
17 |
+
use Twig\Node\BlockReferenceNode;
|
18 |
+
use Twig\Node\BodyNode;
|
19 |
+
use Twig\Node\Expression\AbstractExpression;
|
20 |
+
use Twig\Node\MacroNode;
|
21 |
+
use Twig\Node\ModuleNode;
|
22 |
+
use Twig\Node\Node;
|
23 |
+
use Twig\Node\NodeCaptureInterface;
|
24 |
+
use Twig\Node\NodeOutputInterface;
|
25 |
+
use Twig\Node\PrintNode;
|
26 |
+
use Twig\Node\TextNode;
|
27 |
+
use Twig\NodeTraverser;
|
28 |
+
use Twig\NodeVisitor\NodeVisitorInterface;
|
29 |
+
use Twig\Token;
|
30 |
+
use Twig\TokenParser\TokenParserInterface;
|
31 |
+
use Twig\TokenStream;
|
32 |
+
|
33 |
/**
|
34 |
* Default parser implementation.
|
35 |
*
|
53 |
protected $embeddedTemplates = [];
|
54 |
private $varNameSalt = 0;
|
55 |
|
56 |
+
public function __construct(Environment $env)
|
57 |
{
|
58 |
$this->env = $env;
|
59 |
}
|
83 |
return $this->stream->getSourceContext()->getName();
|
84 |
}
|
85 |
|
86 |
+
public function parse(TokenStream $stream, $test = null, $dropNeedle = false)
|
87 |
{
|
88 |
// push all variables into the stack to keep the current state of the parser
|
89 |
// using get_object_vars() instead of foreach would lead to https://bugs.php.net/71336
|
108 |
}
|
109 |
|
110 |
if (null === $this->expressionParser) {
|
111 |
+
$this->expressionParser = new ExpressionParser($this, $this->env);
|
112 |
}
|
113 |
|
114 |
$this->stream = $stream;
|
125 |
$body = $this->subparse($test, $dropNeedle);
|
126 |
|
127 |
if (null !== $this->parent && null === $body = $this->filterBodyNodes($body)) {
|
128 |
+
$body = new Node();
|
129 |
}
|
130 |
+
} catch (SyntaxError $e) {
|
131 |
if (!$e->getSourceContext()) {
|
132 |
$e->setSourceContext($this->stream->getSourceContext());
|
133 |
}
|
139 |
throw $e;
|
140 |
}
|
141 |
|
142 |
+
$node = new ModuleNode(new BodyNode([$body]), $this->parent, new Node($this->blocks), new Node($this->macros), new Node($this->traits), $this->embeddedTemplates, $stream->getSourceContext());
|
143 |
|
144 |
+
$traverser = new NodeTraverser($this->env, $this->visitors);
|
145 |
|
146 |
$node = $traverser->traverse($node);
|
147 |
|
159 |
$rv = [];
|
160 |
while (!$this->stream->isEOF()) {
|
161 |
switch ($this->getCurrentToken()->getType()) {
|
162 |
+
case Token::TEXT_TYPE:
|
163 |
$token = $this->stream->next();
|
164 |
+
$rv[] = new TextNode($token->getValue(), $token->getLine());
|
165 |
break;
|
166 |
|
167 |
+
case Token::VAR_START_TYPE:
|
168 |
$token = $this->stream->next();
|
169 |
$expr = $this->expressionParser->parseExpression();
|
170 |
+
$this->stream->expect(Token::VAR_END_TYPE);
|
171 |
+
$rv[] = new PrintNode($expr, $token->getLine());
|
172 |
break;
|
173 |
|
174 |
+
case Token::BLOCK_START_TYPE:
|
175 |
$this->stream->next();
|
176 |
$token = $this->getCurrentToken();
|
177 |
|
178 |
+
if (Token::NAME_TYPE !== $token->getType()) {
|
179 |
+
throw new SyntaxError('A block must start with a tag name.', $token->getLine(), $this->stream->getSourceContext());
|
180 |
}
|
181 |
|
182 |
+
if (null !== $test && \call_user_func($test, $token)) {
|
183 |
if ($dropNeedle) {
|
184 |
$this->stream->next();
|
185 |
}
|
186 |
|
187 |
+
if (1 === \count($rv)) {
|
188 |
return $rv[0];
|
189 |
}
|
190 |
|
191 |
+
return new Node($rv, [], $lineno);
|
192 |
}
|
193 |
|
194 |
$subparser = $this->handlers->getTokenParser($token->getValue());
|
195 |
if (null === $subparser) {
|
196 |
if (null !== $test) {
|
197 |
+
$e = new SyntaxError(sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->stream->getSourceContext());
|
198 |
|
199 |
+
if (\is_array($test) && isset($test[0]) && $test[0] instanceof TokenParserInterface) {
|
200 |
$e->appendMessage(sprintf(' (expecting closing tag for the "%s" tag defined near line %s).', $test[0]->getTag(), $lineno));
|
201 |
}
|
202 |
} else {
|
203 |
+
$e = new SyntaxError(sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->stream->getSourceContext());
|
204 |
$e->addSuggestions($token->getValue(), array_keys($this->env->getTags()));
|
205 |
}
|
206 |
|
216 |
break;
|
217 |
|
218 |
default:
|
219 |
+
throw new SyntaxError('Lexer or parser ended up in unsupported state.', $this->getCurrentToken()->getLine(), $this->stream->getSourceContext());
|
220 |
}
|
221 |
}
|
222 |
|
223 |
+
if (1 === \count($rv)) {
|
224 |
return $rv[0];
|
225 |
}
|
226 |
|
227 |
+
return new Node($rv, [], $lineno);
|
228 |
}
|
229 |
|
230 |
/**
|
240 |
/**
|
241 |
* @deprecated since 1.27 (to be removed in 2.0)
|
242 |
*/
|
243 |
+
public function addNodeVisitor(NodeVisitorInterface $visitor)
|
244 |
{
|
245 |
@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0.', E_USER_DEPRECATED);
|
246 |
|
254 |
|
255 |
public function peekBlockStack()
|
256 |
{
|
257 |
+
return $this->blockStack[\count($this->blockStack) - 1];
|
258 |
}
|
259 |
|
260 |
public function popBlockStack()
|
277 |
return $this->blocks[$name];
|
278 |
}
|
279 |
|
280 |
+
public function setBlock($name, BlockNode $value)
|
281 |
{
|
282 |
+
$this->blocks[$name] = new BodyNode([$value], [], $value->getTemplateLine());
|
283 |
}
|
284 |
|
285 |
public function hasMacro($name)
|
287 |
return isset($this->macros[$name]);
|
288 |
}
|
289 |
|
290 |
+
public function setMacro($name, MacroNode $node)
|
291 |
{
|
292 |
if ($this->isReservedMacroName($name)) {
|
293 |
+
throw new SyntaxError(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword.', $name), $node->getTemplateLine(), $this->stream->getSourceContext());
|
294 |
}
|
295 |
|
296 |
$this->macros[$name] = $node;
|
300 |
{
|
301 |
if (null === $this->reservedMacroNames) {
|
302 |
$this->reservedMacroNames = [];
|
303 |
+
$r = new \ReflectionClass($this->env->getBaseTemplateClass());
|
304 |
foreach ($r->getMethods() as $method) {
|
305 |
$methodName = strtolower($method->getName());
|
306 |
|
310 |
}
|
311 |
}
|
312 |
|
313 |
+
return \in_array(strtolower($name), $this->reservedMacroNames);
|
314 |
}
|
315 |
|
316 |
public function addTrait($trait)
|
320 |
|
321 |
public function hasTraits()
|
322 |
{
|
323 |
+
return \count($this->traits) > 0;
|
324 |
}
|
325 |
|
326 |
+
public function embedTemplate(ModuleNode $template)
|
327 |
{
|
328 |
$template->setIndex(mt_rand());
|
329 |
|
330 |
$this->embeddedTemplates[] = $template;
|
331 |
}
|
332 |
|
333 |
+
public function addImportedSymbol($type, $alias, $name = null, AbstractExpression $node = null)
|
334 |
{
|
335 |
$this->importedSymbols[0][$type][$alias] = ['name' => $name, 'node' => $node];
|
336 |
}
|
346 |
|
347 |
public function isMainScope()
|
348 |
{
|
349 |
+
return 1 === \count($this->importedSymbols);
|
350 |
}
|
351 |
|
352 |
public function pushLocalScope()
|
360 |
}
|
361 |
|
362 |
/**
|
363 |
+
* @return ExpressionParser
|
364 |
*/
|
365 |
public function getExpressionParser()
|
366 |
{
|
378 |
}
|
379 |
|
380 |
/**
|
381 |
+
* @return TokenStream
|
382 |
*/
|
383 |
public function getStream()
|
384 |
{
|
386 |
}
|
387 |
|
388 |
/**
|
389 |
+
* @return Token
|
390 |
*/
|
391 |
public function getCurrentToken()
|
392 |
{
|
397 |
{
|
398 |
// check that the body does not contain non-empty output nodes
|
399 |
if (
|
400 |
+
($node instanceof TextNode && !ctype_space($node->getAttribute('data')))
|
401 |
||
|
402 |
+
(!$node instanceof TextNode && !$node instanceof BlockReferenceNode && $node instanceof NodeOutputInterface)
|
403 |
) {
|
404 |
+
if (false !== strpos((string) $node, \chr(0xEF).\chr(0xBB).\chr(0xBF))) {
|
405 |
$t = substr($node->getAttribute('data'), 3);
|
406 |
if ('' === $t || ctype_space($t)) {
|
407 |
// bypass empty nodes starting with a BOM
|
409 |
}
|
410 |
}
|
411 |
|
412 |
+
throw new SyntaxError('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());
|
413 |
}
|
414 |
|
415 |
// bypass nodes that will "capture" the output
|
416 |
+
if ($node instanceof NodeCaptureInterface) {
|
417 |
return $node;
|
418 |
}
|
419 |
|
420 |
+
if ($node instanceof NodeOutputInterface) {
|
421 |
return;
|
422 |
}
|
423 |
|
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
|
25 |
*
|
26 |
-
* @throws
|
27 |
*/
|
28 |
-
public function parse(
|
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 |
}
|
vendor/twig/twig/lib/Twig/Profiler/Dumper/Base.php
CHANGED
@@ -9,6 +9,8 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
12 |
/**
|
13 |
* @author Fabien Potencier <fabien@symfony.com>
|
14 |
*/
|
@@ -16,18 +18,18 @@ abstract class Twig_Profiler_Dumper_Base
|
|
16 |
{
|
17 |
private $root;
|
18 |
|
19 |
-
public function dump(
|
20 |
{
|
21 |
return $this->dumpProfile($profile);
|
22 |
}
|
23 |
|
24 |
-
abstract protected function formatTemplate(
|
25 |
|
26 |
-
abstract protected function formatNonTemplate(
|
27 |
|
28 |
-
abstract protected function formatTime(
|
29 |
|
30 |
-
private function dumpProfile(
|
31 |
{
|
32 |
if ($profile->isRoot()) {
|
33 |
$this->root = $profile->getDuration();
|
@@ -49,7 +51,7 @@ abstract class Twig_Profiler_Dumper_Base
|
|
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 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Profiler\Profile;
|
13 |
+
|
14 |
/**
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
*/
|
18 |
{
|
19 |
private $root;
|
20 |
|
21 |
+
public function dump(Profile $profile)
|
22 |
{
|
23 |
return $this->dumpProfile($profile);
|
24 |
}
|
25 |
|
26 |
+
abstract protected function formatTemplate(Profile $profile, $prefix);
|
27 |
|
28 |
+
abstract protected function formatNonTemplate(Profile $profile, $prefix);
|
29 |
|
30 |
+
abstract protected function formatTime(Profile $profile, $percent);
|
31 |
|
32 |
+
private function dumpProfile(Profile $profile, $prefix = '', $sibling = false)
|
33 |
{
|
34 |
if ($profile->isRoot()) {
|
35 |
$this->root = $profile->getDuration();
|
51 |
$str = sprintf("%s %s\n", $start, $this->formatTime($profile, $percent));
|
52 |
}
|
53 |
|
54 |
+
$nCount = \count($profile->getProfiles());
|
55 |
foreach ($profile as $i => $p) {
|
56 |
$str .= $this->dumpProfile($p, $prefix, $i + 1 !== $nCount);
|
57 |
}
|
vendor/twig/twig/lib/Twig/Profiler/Dumper/Blackfire.php
CHANGED
@@ -9,6 +9,8 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
12 |
/**
|
13 |
* @author Fabien Potencier <fabien@symfony.com>
|
14 |
*
|
@@ -16,7 +18,7 @@
|
|
16 |
*/
|
17 |
class Twig_Profiler_Dumper_Blackfire
|
18 |
{
|
19 |
-
public function dump(
|
20 |
{
|
21 |
$data = [];
|
22 |
$this->dumpProfile('main()', $profile, $data);
|
@@ -38,7 +40,7 @@ EOF;
|
|
38 |
return $str;
|
39 |
}
|
40 |
|
41 |
-
private function dumpChildren($parent,
|
42 |
{
|
43 |
foreach ($profile as $p) {
|
44 |
if ($p->isTemplate()) {
|
@@ -51,7 +53,7 @@ EOF;
|
|
51 |
}
|
52 |
}
|
53 |
|
54 |
-
private function dumpProfile($edge,
|
55 |
{
|
56 |
if (isset($data[$edge])) {
|
57 |
++$data[$edge]['ct'];
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Profiler\Profile;
|
13 |
+
|
14 |
/**
|
15 |
* @author Fabien Potencier <fabien@symfony.com>
|
16 |
*
|
18 |
*/
|
19 |
class Twig_Profiler_Dumper_Blackfire
|
20 |
{
|
21 |
+
public function dump(Profile $profile)
|
22 |
{
|
23 |
$data = [];
|
24 |
$this->dumpProfile('main()', $profile, $data);
|
40 |
return $str;
|
41 |
}
|
42 |
|
43 |
+
private function dumpChildren($parent, Profile $profile, &$data)
|
44 |
{
|
45 |
foreach ($profile as $p) {
|
46 |
if ($p->isTemplate()) {
|
53 |
}
|
54 |
}
|
55 |
|
56 |
+
private function dumpProfile($edge, Profile $profile, &$data)
|
57 |
{
|
58 |
if (isset($data[$edge])) {
|
59 |
++$data[$edge]['ct'];
|
vendor/twig/twig/lib/Twig/Profiler/Dumper/Html.php
CHANGED
@@ -9,12 +9,15 @@
|
|
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
|
18 |
{
|
19 |
private static $colors = [
|
20 |
'block' => '#dfd',
|
@@ -23,22 +26,22 @@ class Twig_Profiler_Dumper_Html extends Twig_Profiler_Dumper_Base
|
|
23 |
'big' => '#d44',
|
24 |
];
|
25 |
|
26 |
-
public function dump(
|
27 |
{
|
28 |
return '<pre>'.parent::dump($profile).'</pre>';
|
29 |
}
|
30 |
|
31 |
-
protected function formatTemplate(
|
32 |
{
|
33 |
return sprintf('%s└ <span style="background-color: %s">%s</span>', $prefix, self::$colors['template'], $profile->getTemplate());
|
34 |
}
|
35 |
|
36 |
-
protected function formatNonTemplate(
|
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(
|
42 |
{
|
43 |
return sprintf('<span style="color: %s">%.2fms/%.0f%%</span>', $percent > 20 ? self::$colors['big'] : 'auto', $profile->getDuration() * 1000, $percent);
|
44 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Profiler\Dumper\BaseDumper;
|
13 |
+
use Twig\Profiler\Profile;
|
14 |
+
|
15 |
/**
|
16 |
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*
|
18 |
* @final
|
19 |
*/
|
20 |
+
class Twig_Profiler_Dumper_Html extends BaseDumper
|
21 |
{
|
22 |
private static $colors = [
|
23 |
'block' => '#dfd',
|
26 |
'big' => '#d44',
|
27 |
];
|
28 |
|
29 |
+
public function dump(Profile $profile)
|
30 |
{
|
31 |
return '<pre>'.parent::dump($profile).'</pre>';
|
32 |
}
|
33 |
|
34 |
+
protected function formatTemplate(Profile $profile, $prefix)
|
35 |
{
|
36 |
return sprintf('%s└ <span style="background-color: %s">%s</span>', $prefix, self::$colors['template'], $profile->getTemplate());
|
37 |
}
|
38 |
|
39 |
+
protected function formatNonTemplate(Profile $profile, $prefix)
|
40 |
{
|
41 |
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());
|
42 |
}
|
43 |
|
44 |
+
protected function formatTime(Profile $profile, $percent)
|
45 |
{
|
46 |
return sprintf('<span style="color: %s">%.2fms/%.0f%%</span>', $percent > 20 ? self::$colors['big'] : 'auto', $profile->getDuration() * 1000, $percent);
|
47 |
}
|
vendor/twig/twig/lib/Twig/Profiler/Dumper/Text.php
CHANGED
@@ -9,24 +9,27 @@
|
|
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
|
18 |
{
|
19 |
-
protected function formatTemplate(
|
20 |
{
|
21 |
return sprintf('%s└ %s', $prefix, $profile->getTemplate());
|
22 |
}
|
23 |
|
24 |
-
protected function formatNonTemplate(
|
25 |
{
|
26 |
return sprintf('%s└ %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), $profile->getName());
|
27 |
}
|
28 |
|
29 |
-
protected function formatTime(
|
30 |
{
|
31 |
return sprintf('%.2fms/%.0f%%', $profile->getDuration() * 1000, $percent);
|
32 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Profiler\Dumper\BaseDumper;
|
13 |
+
use Twig\Profiler\Profile;
|
14 |
+
|
15 |
/**
|
16 |
* @author Fabien Potencier <fabien@symfony.com>
|
17 |
*
|
18 |
* @final
|
19 |
*/
|
20 |
+
class Twig_Profiler_Dumper_Text extends BaseDumper
|
21 |
{
|
22 |
+
protected function formatTemplate(Profile $profile, $prefix)
|
23 |
{
|
24 |
return sprintf('%s└ %s', $prefix, $profile->getTemplate());
|
25 |
}
|
26 |
|
27 |
+
protected function formatNonTemplate(Profile $profile, $prefix)
|
28 |
{
|
29 |
return sprintf('%s└ %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), $profile->getName());
|
30 |
}
|
31 |
|
32 |
+
protected function formatTime(Profile $profile, $percent)
|
33 |
{
|
34 |
return sprintf('%.2fms/%.0f%%', $profile->getDuration() * 1000, $percent);
|
35 |
}
|
vendor/twig/twig/lib/Twig/Profiler/Node/EnterProfile.php
CHANGED
@@ -9,25 +9,28 @@
|
|
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
|
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(
|
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
|
31 |
->repr($this->getAttribute('type'))
|
32 |
->raw(', ')
|
33 |
->repr($this->getAttribute('name'))
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Node;
|
14 |
+
|
15 |
/**
|
16 |
* Represents a profile enter node.
|
17 |
*
|
18 |
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
*/
|
20 |
+
class Twig_Profiler_Node_EnterProfile extends Node
|
21 |
{
|
22 |
public function __construct($extensionName, $type, $name, $varName)
|
23 |
{
|
24 |
parent::__construct([], ['extension_name' => $extensionName, 'name' => $name, 'type' => $type, 'var_name' => $varName]);
|
25 |
}
|
26 |
|
27 |
+
public function compile(Compiler $compiler)
|
28 |
{
|
29 |
$compiler
|
30 |
->write(sprintf('$%s = $this->env->getExtension(', $this->getAttribute('var_name')))
|
31 |
->repr($this->getAttribute('extension_name'))
|
32 |
->raw(");\n")
|
33 |
+
->write(sprintf('$%s->enter($%s = new \Twig\Profiler\Profile($this->getTemplateName(), ', $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof'))
|
34 |
->repr($this->getAttribute('type'))
|
35 |
->raw(', ')
|
36 |
->repr($this->getAttribute('name'))
|
vendor/twig/twig/lib/Twig/Profiler/Node/LeaveProfile.php
CHANGED
@@ -9,19 +9,22 @@
|
|
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
|
18 |
{
|
19 |
public function __construct($varName)
|
20 |
{
|
21 |
parent::__construct([], ['var_name' => $varName]);
|
22 |
}
|
23 |
|
24 |
-
public function compile(
|
25 |
{
|
26 |
$compiler
|
27 |
->write("\n")
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Node\Node;
|
14 |
+
|
15 |
/**
|
16 |
* Represents a profile leave node.
|
17 |
*
|
18 |
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
*/
|
20 |
+
class Twig_Profiler_Node_LeaveProfile extends Node
|
21 |
{
|
22 |
public function __construct($varName)
|
23 |
{
|
24 |
parent::__construct([], ['var_name' => $varName]);
|
25 |
}
|
26 |
|
27 |
+
public function compile(Compiler $compiler)
|
28 |
{
|
29 |
$compiler
|
30 |
->write("\n")
|
vendor/twig/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php
CHANGED
@@ -9,12 +9,23 @@
|
|
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
|
18 |
{
|
19 |
private $extensionName;
|
20 |
|
@@ -23,30 +34,30 @@ class Twig_Profiler_NodeVisitor_Profiler extends Twig_BaseNodeVisitor
|
|
23 |
$this->extensionName = $extensionName;
|
24 |
}
|
25 |
|
26 |
-
protected function doEnterNode(
|
27 |
{
|
28 |
return $node;
|
29 |
}
|
30 |
|
31 |
-
protected function doLeaveNode(
|
32 |
{
|
33 |
-
if ($node instanceof
|
34 |
$varName = $this->getVarName();
|
35 |
-
$node->setNode('display_start', new
|
36 |
-
$node->setNode('display_end', new
|
37 |
-
} elseif ($node instanceof
|
38 |
$varName = $this->getVarName();
|
39 |
-
$node->setNode('body', new
|
40 |
-
new
|
41 |
$node->getNode('body'),
|
42 |
-
new
|
43 |
]));
|
44 |
-
} elseif ($node instanceof
|
45 |
$varName = $this->getVarName();
|
46 |
-
$node->setNode('body', new
|
47 |
-
new
|
48 |
$node->getNode('body'),
|
49 |
-
new
|
50 |
]));
|
51 |
}
|
52 |
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Environment;
|
13 |
+
use Twig\Node\BlockNode;
|
14 |
+
use Twig\Node\BodyNode;
|
15 |
+
use Twig\Node\MacroNode;
|
16 |
+
use Twig\Node\ModuleNode;
|
17 |
+
use Twig\Node\Node;
|
18 |
+
use Twig\NodeVisitor\AbstractNodeVisitor;
|
19 |
+
use Twig\Profiler\Node\EnterProfileNode;
|
20 |
+
use Twig\Profiler\Node\LeaveProfileNode;
|
21 |
+
use Twig\Profiler\Profile;
|
22 |
+
|
23 |
/**
|
24 |
* @author Fabien Potencier <fabien@symfony.com>
|
25 |
*
|
26 |
* @final
|
27 |
*/
|
28 |
+
class Twig_Profiler_NodeVisitor_Profiler extends AbstractNodeVisitor
|
29 |
{
|
30 |
private $extensionName;
|
31 |
|
34 |
$this->extensionName = $extensionName;
|
35 |
}
|
36 |
|
37 |
+
protected function doEnterNode(Node $node, Environment $env)
|
38 |
{
|
39 |
return $node;
|
40 |
}
|
41 |
|
42 |
+
protected function doLeaveNode(Node $node, Environment $env)
|
43 |
{
|
44 |
+
if ($node instanceof ModuleNode) {
|
45 |
$varName = $this->getVarName();
|
46 |
+
$node->setNode('display_start', new Node([new EnterProfileNode($this->extensionName, Profile::TEMPLATE, $node->getTemplateName(), $varName), $node->getNode('display_start')]));
|
47 |
+
$node->setNode('display_end', new Node([new LeaveProfileNode($varName), $node->getNode('display_end')]));
|
48 |
+
} elseif ($node instanceof BlockNode) {
|
49 |
$varName = $this->getVarName();
|
50 |
+
$node->setNode('body', new BodyNode([
|
51 |
+
new EnterProfileNode($this->extensionName, Profile::BLOCK, $node->getAttribute('name'), $varName),
|
52 |
$node->getNode('body'),
|
53 |
+
new LeaveProfileNode($varName),
|
54 |
]));
|
55 |
+
} elseif ($node instanceof MacroNode) {
|
56 |
$varName = $this->getVarName();
|
57 |
+
$node->setNode('body', new BodyNode([
|
58 |
+
new EnterProfileNode($this->extensionName, Profile::MACRO, $node->getAttribute('name'), $varName),
|
59 |
$node->getNode('body'),
|
60 |
+
new LeaveProfileNode($varName),
|
61 |
]));
|
62 |
}
|
63 |
|
vendor/twig/twig/lib/Twig/Profiler/Profile.php
CHANGED
@@ -14,7 +14,7 @@
|
|
14 |
*
|
15 |
* @final
|
16 |
*/
|
17 |
-
class Twig_Profiler_Profile implements IteratorAggregate, Serializable
|
18 |
{
|
19 |
const ROOT = 'ROOT';
|
20 |
const BLOCK = 'block';
|
@@ -153,7 +153,7 @@ class Twig_Profiler_Profile implements IteratorAggregate, Serializable
|
|
153 |
|
154 |
public function getIterator()
|
155 |
{
|
156 |
-
return new ArrayIterator($this->profiles);
|
157 |
}
|
158 |
|
159 |
public function serialize()
|
14 |
*
|
15 |
* @final
|
16 |
*/
|
17 |
+
class Twig_Profiler_Profile implements \IteratorAggregate, Serializable
|
18 |
{
|
19 |
const ROOT = 'ROOT';
|
20 |
const BLOCK = 'block';
|
153 |
|
154 |
public function getIterator()
|
155 |
{
|
156 |
+
return new \ArrayIterator($this->profiles);
|
157 |
}
|
158 |
|
159 |
public function serialize()
|
vendor/twig/twig/lib/Twig/Sandbox/SecurityError.php
CHANGED
@@ -9,12 +9,14 @@
|
|
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
|
18 |
{
|
19 |
}
|
20 |
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Error\Error;
|
13 |
+
|
14 |
/**
|
15 |
* Exception thrown when a security error occurs at runtime.
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
+
class Twig_Sandbox_SecurityError extends Error
|
20 |
{
|
21 |
}
|
22 |
|
vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php
CHANGED
@@ -9,16 +9,18 @@
|
|
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
|
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;
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Sandbox\SecurityError;
|
13 |
+
|
14 |
/**
|
15 |
* Exception thrown when a not allowed filter is used in a template.
|
16 |
*
|
17 |
* @author Martin Hasoň <martin.hason@gmail.com>
|
18 |
*/
|
19 |
+
class Twig_Sandbox_SecurityNotAllowedFilterError extends SecurityError
|
20 |
{
|
21 |
private $filterName;
|
22 |
|
23 |
+
public function __construct($message, $functionName, $lineno = -1, $filename = null, \Exception $previous = null)
|
24 |
{
|
25 |
parent::__construct($message, $lineno, $filename, $previous);
|
26 |
$this->filterName = $functionName;
|
vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php
CHANGED
@@ -9,16 +9,18 @@
|
|
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
|
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;
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Sandbox\SecurityError;
|
13 |
+
|
14 |
/**
|
15 |
* Exception thrown when a not allowed function is used in a template.
|
16 |
*
|
17 |
* @author Martin Hasoň <martin.hason@gmail.com>
|
18 |
*/
|
19 |
+
class Twig_Sandbox_SecurityNotAllowedFunctionError extends SecurityError
|
20 |
{
|
21 |
private $functionName;
|
22 |
|
23 |
+
public function __construct($message, $functionName, $lineno = -1, $filename = null, \Exception $previous = null)
|
24 |
{
|
25 |
parent::__construct($message, $lineno, $filename, $previous);
|
26 |
$this->functionName = $functionName;
|
vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedMethodError.php
CHANGED
@@ -9,17 +9,19 @@
|
|
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
|
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;
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Sandbox\SecurityError;
|
13 |
+
|
14 |
/**
|
15 |
* Exception thrown when a not allowed class method is used in a template.
|
16 |
*
|
17 |
* @author Kit Burton-Senior <mail@kitbs.com>
|
18 |
*/
|
19 |
+
class Twig_Sandbox_SecurityNotAllowedMethodError extends SecurityError
|
20 |
{
|
21 |
private $className;
|
22 |
private $methodName;
|
23 |
|
24 |
+
public function __construct($message, $className, $methodName, $lineno = -1, $filename = null, \Exception $previous = null)
|
25 |
{
|
26 |
parent::__construct($message, $lineno, $filename, $previous);
|
27 |
$this->className = $className;
|
vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedPropertyError.php
CHANGED
@@ -9,17 +9,19 @@
|
|
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
|
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;
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Sandbox\SecurityError;
|
13 |
+
|
14 |
/**
|
15 |
* Exception thrown when a not allowed class property is used in a template.
|
16 |
*
|
17 |
* @author Kit Burton-Senior <mail@kitbs.com>
|
18 |
*/
|
19 |
+
class Twig_Sandbox_SecurityNotAllowedPropertyError extends SecurityError
|
20 |
{
|
21 |
private $className;
|
22 |
private $propertyName;
|
23 |
|
24 |
+
public function __construct($message, $className, $propertyName, $lineno = -1, $filename = null, \Exception $previous = null)
|
25 |
{
|
26 |
parent::__construct($message, $lineno, $filename, $previous);
|
27 |
$this->className = $className;
|
vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php
CHANGED
@@ -9,16 +9,18 @@
|
|
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
|
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;
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Sandbox\SecurityError;
|
13 |
+
|
14 |
/**
|
15 |
* Exception thrown when a not allowed tag is used in a template.
|
16 |
*
|
17 |
* @author Martin Hasoň <martin.hason@gmail.com>
|
18 |
*/
|
19 |
+
class Twig_Sandbox_SecurityNotAllowedTagError extends SecurityError
|
20 |
{
|
21 |
private $tagName;
|
22 |
|
23 |
+
public function __construct($message, $tagName, $lineno = -1, $filename = null, \Exception $previous = null)
|
24 |
{
|
25 |
parent::__construct($message, $lineno, $filename, $previous);
|
26 |
$this->tagName = $tagName;
|
vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php
CHANGED
@@ -9,6 +9,14 @@
|
|
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 |
*
|
@@ -16,7 +24,7 @@
|
|
16 |
*
|
17 |
* @author Fabien Potencier <fabien@symfony.com>
|
18 |
*/
|
19 |
-
class Twig_Sandbox_SecurityPolicy implements
|
20 |
{
|
21 |
protected $allowedTags;
|
22 |
protected $allowedFilters;
|
@@ -47,7 +55,7 @@ class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterfac
|
|
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 |
|
@@ -64,27 +72,27 @@ class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterfac
|
|
64 |
public function checkSecurity($tags, $filters, $functions)
|
65 |
{
|
66 |
foreach ($tags as $tag) {
|
67 |
-
if (
|
68 |
-
throw new
|
69 |
}
|
70 |
}
|
71 |
|
72 |
foreach ($filters as $filter) {
|
73 |
-
if (
|
74 |
-
throw new
|
75 |
}
|
76 |
}
|
77 |
|
78 |
foreach ($functions as $function) {
|
79 |
-
if (
|
80 |
-
throw new
|
81 |
}
|
82 |
}
|
83 |
}
|
84 |
|
85 |
public function checkMethodAllowed($obj, $method)
|
86 |
{
|
87 |
-
if ($obj instanceof Twig_TemplateInterface || $obj instanceof
|
88 |
return true;
|
89 |
}
|
90 |
|
@@ -92,15 +100,15 @@ class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterfac
|
|
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
|
104 |
}
|
105 |
}
|
106 |
|
@@ -109,15 +117,15 @@ class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterfac
|
|
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
|
121 |
}
|
122 |
}
|
123 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Markup;
|
13 |
+
use Twig\Sandbox\SecurityNotAllowedFilterError;
|
14 |
+
use Twig\Sandbox\SecurityNotAllowedFunctionError;
|
15 |
+
use Twig\Sandbox\SecurityNotAllowedMethodError;
|
16 |
+
use Twig\Sandbox\SecurityNotAllowedPropertyError;
|
17 |
+
use Twig\Sandbox\SecurityNotAllowedTagError;
|
18 |
+
use Twig\Sandbox\SecurityPolicyInterface;
|
19 |
+
|
20 |
/**
|
21 |
* Represents a security policy which need to be enforced when sandbox mode is enabled.
|
22 |
*
|
24 |
*
|
25 |
* @author Fabien Potencier <fabien@symfony.com>
|
26 |
*/
|
27 |
+
class Twig_Sandbox_SecurityPolicy implements SecurityPolicyInterface
|
28 |
{
|
29 |
protected $allowedTags;
|
30 |
protected $allowedFilters;
|
55 |
{
|
56 |
$this->allowedMethods = [];
|
57 |
foreach ($methods as $class => $m) {
|
58 |
+
$this->allowedMethods[$class] = array_map('strtolower', \is_array($m) ? $m : [$m]);
|
59 |
}
|
60 |
}
|
61 |
|
72 |
public function checkSecurity($tags, $filters, $functions)
|
73 |
{
|
74 |
foreach ($tags as $tag) {
|
75 |
+
if (!\in_array($tag, $this->allowedTags)) {
|
76 |
+
throw new SecurityNotAllowedTagError(sprintf('Tag "%s" is not allowed.', $tag), $tag);
|
77 |
}
|
78 |
}
|
79 |
|
80 |
foreach ($filters as $filter) {
|
81 |
+
if (!\in_array($filter, $this->allowedFilters)) {
|
82 |
+
throw new SecurityNotAllowedFilterError(sprintf('Filter "%s" is not allowed.', $filter), $filter);
|
83 |
}
|
84 |
}
|
85 |
|
86 |
foreach ($functions as $function) {
|
87 |
+
if (!\in_array($function, $this->allowedFunctions)) {
|
88 |
+
throw new SecurityNotAllowedFunctionError(sprintf('Function "%s" is not allowed.', $function), $function);
|
89 |
}
|
90 |
}
|
91 |
}
|
92 |
|
93 |
public function checkMethodAllowed($obj, $method)
|
94 |
{
|
95 |
+
if ($obj instanceof Twig_TemplateInterface || $obj instanceof Markup) {
|
96 |
return true;
|
97 |
}
|
98 |
|
100 |
$method = strtolower($method);
|
101 |
foreach ($this->allowedMethods as $class => $methods) {
|
102 |
if ($obj instanceof $class) {
|
103 |
+
$allowed = \in_array($method, $methods);
|
104 |
|
105 |
break;
|
106 |
}
|
107 |
}
|
108 |
|
109 |
if (!$allowed) {
|
110 |
+
$class = \get_class($obj);
|
111 |
+
throw new SecurityNotAllowedMethodError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, $class), $class, $method);
|
112 |
}
|
113 |
}
|
114 |
|
117 |
$allowed = false;
|
118 |
foreach ($this->allowedProperties as $class => $properties) {
|
119 |
if ($obj instanceof $class) {
|
120 |
+
$allowed = \in_array($property, \is_array($properties) ? $properties : [$properties]);
|
121 |
|
122 |
break;
|
123 |
}
|
124 |
}
|
125 |
|
126 |
if (!$allowed) {
|
127 |
+
$class = \get_class($obj);
|
128 |
+
throw new SecurityNotAllowedPropertyError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, $class), $class, $property);
|
129 |
}
|
130 |
}
|
131 |
}
|
vendor/twig/twig/lib/Twig/SimpleFilter.php
CHANGED
@@ -9,6 +9,8 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
12 |
/**
|
13 |
* Represents a template filter.
|
14 |
*
|
@@ -35,7 +37,7 @@ class Twig_SimpleFilter
|
|
35 |
'is_safe_callback' => null,
|
36 |
'pre_escape' => null,
|
37 |
'preserves_safety' => null,
|
38 |
-
'node_class' => '
|
39 |
'deprecated' => false,
|
40 |
'alternative' => null,
|
41 |
], $options);
|
@@ -76,14 +78,14 @@ class Twig_SimpleFilter
|
|
76 |
return $this->options['needs_context'];
|
77 |
}
|
78 |
|
79 |
-
public function getSafe(
|
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 |
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Node\Node;
|
13 |
+
|
14 |
/**
|
15 |
* Represents a template filter.
|
16 |
*
|
37 |
'is_safe_callback' => null,
|
38 |
'pre_escape' => null,
|
39 |
'preserves_safety' => null,
|
40 |
+
'node_class' => '\Twig\Node\Expression\FilterExpression',
|
41 |
'deprecated' => false,
|
42 |
'alternative' => null,
|
43 |
], $options);
|
78 |
return $this->options['needs_context'];
|
79 |
}
|
80 |
|
81 |
+
public function getSafe(Node $filterArgs)
|
82 |
{
|
83 |
if (null !== $this->options['is_safe']) {
|
84 |
return $this->options['is_safe'];
|
85 |
}
|
86 |
|
87 |
if (null !== $this->options['is_safe_callback']) {
|
88 |
+
return \call_user_func($this->options['is_safe_callback'], $filterArgs);
|
89 |
}
|
90 |
}
|
91 |
|
vendor/twig/twig/lib/Twig/SimpleFunction.php
CHANGED
@@ -9,6 +9,8 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
12 |
/**
|
13 |
* Represents a template function.
|
14 |
*
|
@@ -33,7 +35,7 @@ class Twig_SimpleFunction
|
|
33 |
'is_variadic' => false,
|
34 |
'is_safe' => null,
|
35 |
'is_safe_callback' => null,
|
36 |
-
'node_class' => '
|
37 |
'deprecated' => false,
|
38 |
'alternative' => null,
|
39 |
], $options);
|
@@ -74,14 +76,14 @@ class Twig_SimpleFunction
|
|
74 |
return $this->options['needs_context'];
|
75 |
}
|
76 |
|
77 |
-
public function getSafe(
|
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 [];
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Node\Node;
|
13 |
+
|
14 |
/**
|
15 |
* Represents a template function.
|
16 |
*
|
35 |
'is_variadic' => false,
|
36 |
'is_safe' => null,
|
37 |
'is_safe_callback' => null,
|
38 |
+
'node_class' => '\Twig\Node\Expression\FunctionExpression',
|
39 |
'deprecated' => false,
|
40 |
'alternative' => null,
|
41 |
], $options);
|
76 |
return $this->options['needs_context'];
|
77 |
}
|
78 |
|
79 |
+
public function getSafe(Node $functionArgs)
|
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'], $functionArgs);
|
87 |
}
|
88 |
|
89 |
return [];
|
vendor/twig/twig/lib/Twig/SimpleTest.php
CHANGED
@@ -30,7 +30,7 @@ class Twig_SimpleTest
|
|
30 |
$this->callable = $callable;
|
31 |
$this->options = array_merge([
|
32 |
'is_variadic' => false,
|
33 |
-
'node_class' => '
|
34 |
'deprecated' => false,
|
35 |
'alternative' => null,
|
36 |
], $options);
|
30 |
$this->callable = $callable;
|
31 |
$this->options = array_merge([
|
32 |
'is_variadic' => false,
|
33 |
+
'node_class' => '\Twig\Node\Expression\TestExpression',
|
34 |
'deprecated' => false,
|
35 |
'alternative' => null,
|
36 |
], $options);
|
vendor/twig/twig/lib/Twig/SourceContextLoaderInterface.php
CHANGED
@@ -9,6 +9,9 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Adds a getSourceContext() method for loaders.
|
14 |
*
|
@@ -23,9 +26,9 @@ interface Twig_SourceContextLoaderInterface
|
|
23 |
*
|
24 |
* @param string $name The template logical name
|
25 |
*
|
26 |
-
* @return
|
27 |
*
|
28 |
-
* @throws
|
29 |
*/
|
30 |
public function getSourceContext($name);
|
31 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Error\LoaderError;
|
13 |
+
use Twig\Source;
|
14 |
+
|
15 |
/**
|
16 |
* Adds a getSourceContext() method for loaders.
|
17 |
*
|
26 |
*
|
27 |
* @param string $name The template logical name
|
28 |
*
|
29 |
+
* @return Source
|
30 |
*
|
31 |
+
* @throws LoaderError When $name is not found
|
32 |
*/
|
33 |
public function getSourceContext($name);
|
34 |
}
|
vendor/twig/twig/lib/Twig/Template.php
CHANGED
@@ -10,6 +10,14 @@
|
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
/**
|
14 |
* Default base class for compiled templates.
|
15 |
*
|
@@ -34,7 +42,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
34 |
protected $blocks = [];
|
35 |
protected $traits = [];
|
36 |
|
37 |
-
public function __construct(
|
38 |
{
|
39 |
$this->env = $env;
|
40 |
}
|
@@ -83,11 +91,11 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
83 |
/**
|
84 |
* Returns information about the original template source code.
|
85 |
*
|
86 |
-
* @return
|
87 |
*/
|
88 |
public function getSourceContext()
|
89 |
{
|
90 |
-
return new
|
91 |
}
|
92 |
|
93 |
/**
|
@@ -108,7 +116,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
108 |
*
|
109 |
* @param array $context
|
110 |
*
|
111 |
-
* @return Twig_TemplateInterface|
|
112 |
*
|
113 |
* @internal
|
114 |
*/
|
@@ -125,14 +133,14 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
125 |
return false;
|
126 |
}
|
127 |
|
128 |
-
if ($parent instanceof self || $parent instanceof
|
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 (
|
136 |
$e->setSourceContext(null);
|
137 |
$e->guess();
|
138 |
|
@@ -173,7 +181,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
173 |
} elseif (false !== $parent = $this->getParent($context)) {
|
174 |
$parent->displayBlock($name, $context, $blocks, false);
|
175 |
} else {
|
176 |
-
throw new
|
177 |
}
|
178 |
}
|
179 |
|
@@ -207,13 +215,13 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
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 (
|
217 |
if (!$e->getSourceContext()) {
|
218 |
$e->setSourceContext($template->getSourceContext());
|
219 |
}
|
@@ -226,8 +234,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
226 |
}
|
227 |
|
228 |
throw $e;
|
229 |
-
} catch (Exception $e) {
|
230 |
-
throw new
|
231 |
}
|
232 |
} elseif (false !== $parent = $this->getParent($context)) {
|
233 |
$parent->displayBlock($name, $context, array_merge($this->blocks, $blocks), false);
|
@@ -351,18 +359,18 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
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
|
359 |
return $template;
|
360 |
}
|
361 |
|
362 |
return $this->env->loadTemplate($template, $index);
|
363 |
-
} catch (
|
364 |
if (!$e->getSourceContext()) {
|
365 |
-
$e->setSourceContext($templateName ? new
|
366 |
}
|
367 |
|
368 |
if ($e->getTemplateLine()) {
|
@@ -405,13 +413,13 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
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 |
}
|
@@ -426,7 +434,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
426 |
{
|
427 |
try {
|
428 |
$this->doDisplay($context, $blocks);
|
429 |
-
} catch (
|
430 |
if (!$e->getSourceContext()) {
|
431 |
$e->setSourceContext($this->getSourceContext());
|
432 |
}
|
@@ -439,8 +447,8 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
439 |
}
|
440 |
|
441 |
throw $e;
|
442 |
-
} catch (Exception $e) {
|
443 |
-
throw new
|
444 |
}
|
445 |
}
|
446 |
|
@@ -469,18 +477,18 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
469 |
*
|
470 |
* @return mixed The content of the context variable
|
471 |
*
|
472 |
-
* @throws
|
473 |
*
|
474 |
* @internal
|
475 |
*/
|
476 |
final protected function getContext($context, $item, $ignoreStrictCheck = false)
|
477 |
{
|
478 |
-
if (
|
479 |
if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
|
480 |
return;
|
481 |
}
|
482 |
|
483 |
-
throw new
|
484 |
}
|
485 |
|
486 |
return $context[$item];
|
@@ -498,7 +506,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
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
|
502 |
*
|
503 |
* @internal
|
504 |
*/
|
@@ -506,9 +514,9 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
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) {
|
@@ -518,7 +526,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
518 |
return $object[$arrayItem];
|
519 |
}
|
520 |
|
521 |
-
if (self::ARRAY_CALL === $type ||
|
522 |
if ($isDefinedTest) {
|
523 |
return false;
|
524 |
}
|
@@ -528,10 +536,10 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
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 {
|
@@ -541,19 +549,19 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
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
|
553 |
}
|
554 |
}
|
555 |
|
556 |
-
if (
|
557 |
if ($isDefinedTest) {
|
558 |
return false;
|
559 |
}
|
@@ -564,40 +572,40 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
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
|
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('
|
584 |
-
$this->env->getExtension('
|
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;
|
@@ -655,15 +663,15 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
655 |
return;
|
656 |
}
|
657 |
|
658 |
-
throw new
|
659 |
}
|
660 |
|
661 |
if ($isDefinedTest) {
|
662 |
return true;
|
663 |
}
|
664 |
|
665 |
-
if ($this->env->hasExtension('
|
666 |
-
$this->env->getExtension('
|
667 |
}
|
668 |
|
669 |
// Some objects throw exceptions when they have __call, and the method we try
|
@@ -672,9 +680,9 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
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 |
}
|
@@ -694,7 +702,7 @@ abstract class Twig_Template implements Twig_TemplateInterface
|
|
694 |
}
|
695 |
@trigger_error($message, E_USER_DEPRECATED);
|
696 |
|
697 |
-
return '' === $ret ? '' : new
|
698 |
}
|
699 |
|
700 |
return $ret;
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Environment;
|
14 |
+
use Twig\Error\Error;
|
15 |
+
use Twig\Error\LoaderError;
|
16 |
+
use Twig\Error\RuntimeError;
|
17 |
+
use Twig\Markup;
|
18 |
+
use Twig\Source;
|
19 |
+
use Twig\TemplateWrapper;
|
20 |
+
|
21 |
/**
|
22 |
* Default base class for compiled templates.
|
23 |
*
|
42 |
protected $blocks = [];
|
43 |
protected $traits = [];
|
44 |
|
45 |
+
public function __construct(Environment $env)
|
46 |
{
|
47 |
$this->env = $env;
|
48 |
}
|
91 |
/**
|
92 |
* Returns information about the original template source code.
|
93 |
*
|
94 |
+
* @return Source
|
95 |
*/
|
96 |
public function getSourceContext()
|
97 |
{
|
98 |
+
return new Source('', $this->getTemplateName());
|
99 |
}
|
100 |
|
101 |
/**
|
116 |
*
|
117 |
* @param array $context
|
118 |
*
|
119 |
+
* @return Twig_TemplateInterface|TemplateWrapper|false The parent template or false if there is no parent
|
120 |
*
|
121 |
* @internal
|
122 |
*/
|
133 |
return false;
|
134 |
}
|
135 |
|
136 |
+
if ($parent instanceof self || $parent instanceof TemplateWrapper) {
|
137 |
return $this->parents[$parent->getSourceContext()->getName()] = $parent;
|
138 |
}
|
139 |
|
140 |
if (!isset($this->parents[$parent])) {
|
141 |
$this->parents[$parent] = $this->loadTemplate($parent);
|
142 |
}
|
143 |
+
} catch (LoaderError $e) {
|
144 |
$e->setSourceContext(null);
|
145 |
$e->guess();
|
146 |
|
181 |
} elseif (false !== $parent = $this->getParent($context)) {
|
182 |
$parent->displayBlock($name, $context, $blocks, false);
|
183 |
} else {
|
184 |
+
throw new RuntimeError(sprintf('The template has no parent and no traits defining the "%s" block.', $name), -1, $this->getSourceContext());
|
185 |
}
|
186 |
}
|
187 |
|
215 |
|
216 |
// avoid RCEs when sandbox is enabled
|
217 |
if (null !== $template && !$template instanceof self) {
|
218 |
+
throw new \LogicException('A block must be a method on a Twig_Template instance.');
|
219 |
}
|
220 |
|
221 |
if (null !== $template) {
|
222 |
try {
|
223 |
$template->$block($context, $blocks);
|
224 |
+
} catch (Error $e) {
|
225 |
if (!$e->getSourceContext()) {
|
226 |
$e->setSourceContext($template->getSourceContext());
|
227 |
}
|
234 |
}
|
235 |
|
236 |
throw $e;
|
237 |
+
} catch (\Exception $e) {
|
238 |
+
throw new RuntimeError(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getSourceContext(), $e);
|
239 |
}
|
240 |
} elseif (false !== $parent = $this->getParent($context)) {
|
241 |
$parent->displayBlock($name, $context, array_merge($this->blocks, $blocks), false);
|
359 |
protected function loadTemplate($template, $templateName = null, $line = null, $index = null)
|
360 |
{
|
361 |
try {
|
362 |
+
if (\is_array($template)) {
|
363 |
return $this->env->resolveTemplate($template);
|
364 |
}
|
365 |
|
366 |
+
if ($template instanceof self || $template instanceof TemplateWrapper) {
|
367 |
return $template;
|
368 |
}
|
369 |
|
370 |
return $this->env->loadTemplate($template, $index);
|
371 |
+
} catch (Error $e) {
|
372 |
if (!$e->getSourceContext()) {
|
373 |
+
$e->setSourceContext($templateName ? new Source('', $templateName) : $this->getSourceContext());
|
374 |
}
|
375 |
|
376 |
if ($e->getTemplateLine()) {
|
413 |
ob_start();
|
414 |
try {
|
415 |
$this->display($context);
|
416 |
+
} catch (\Exception $e) {
|
417 |
while (ob_get_level() > $level) {
|
418 |
ob_end_clean();
|
419 |
}
|
420 |
|
421 |
throw $e;
|
422 |
+
} catch (\Throwable $e) {
|
423 |
while (ob_get_level() > $level) {
|
424 |
ob_end_clean();
|
425 |
}
|
434 |
{
|
435 |
try {
|
436 |
$this->doDisplay($context, $blocks);
|
437 |
+
} catch (Error $e) {
|
438 |
if (!$e->getSourceContext()) {
|
439 |
$e->setSourceContext($this->getSourceContext());
|
440 |
}
|
447 |
}
|
448 |
|
449 |
throw $e;
|
450 |
+
} catch (\Exception $e) {
|
451 |
+
throw new RuntimeError(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getSourceContext(), $e);
|
452 |
}
|
453 |
}
|
454 |
|
477 |
*
|
478 |
* @return mixed The content of the context variable
|
479 |
*
|
480 |
+
* @throws RuntimeError if the variable does not exist and Twig is running in strict mode
|
481 |
*
|
482 |
* @internal
|
483 |
*/
|
484 |
final protected function getContext($context, $item, $ignoreStrictCheck = false)
|
485 |
{
|
486 |
+
if (!\array_key_exists($item, $context)) {
|
487 |
if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
|
488 |
return;
|
489 |
}
|
490 |
|
491 |
+
throw new RuntimeError(sprintf('Variable "%s" does not exist.', $item), -1, $this->getSourceContext());
|
492 |
}
|
493 |
|
494 |
return $context[$item];
|
506 |
*
|
507 |
* @return mixed The attribute value, or a Boolean when $isDefinedTest is true, or null when the attribute is not set and $ignoreStrictCheck is true
|
508 |
*
|
509 |
+
* @throws RuntimeError if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false
|
510 |
*
|
511 |
* @internal
|
512 |
*/
|
514 |
{
|
515 |
// array
|
516 |
if (self::METHOD_CALL !== $type) {
|
517 |
+
$arrayItem = \is_bool($item) || \is_float($item) ? (int) $item : $item;
|
518 |
|
519 |
+
if (((\is_array($object) || $object instanceof \ArrayObject) && (isset($object[$arrayItem]) || \array_key_exists($arrayItem, $object)))
|
520 |
|| ($object instanceof ArrayAccess && isset($object[$arrayItem]))
|
521 |
) {
|
522 |
if ($isDefinedTest) {
|
526 |
return $object[$arrayItem];
|
527 |
}
|
528 |
|
529 |
+
if (self::ARRAY_CALL === $type || !\is_object($object)) {
|
530 |
if ($isDefinedTest) {
|
531 |
return false;
|
532 |
}
|
536 |
}
|
537 |
|
538 |
if ($object instanceof ArrayAccess) {
|
539 |
+
$message = sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist.', $arrayItem, \get_class($object));
|
540 |
+
} elseif (\is_object($object)) {
|
541 |
+
$message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface.', $item, \get_class($object));
|
542 |
+
} elseif (\is_array($object)) {
|
543 |
if (empty($object)) {
|
544 |
$message = sprintf('Key "%s" does not exist as the array is empty.', $arrayItem);
|
545 |
} else {
|
549 |
if (null === $object) {
|
550 |
$message = sprintf('Impossible to access a key ("%s") on a null variable.', $item);
|
551 |
} else {
|
552 |
+
$message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s").', $item, \gettype($object), $object);
|
553 |
}
|
554 |
} elseif (null === $object) {
|
555 |
$message = sprintf('Impossible to access an attribute ("%s") on a null variable.', $item);
|
556 |
} else {
|
557 |
+
$message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s").', $item, \gettype($object), $object);
|
558 |
}
|
559 |
|
560 |
+
throw new RuntimeError($message, -1, $this->getSourceContext());
|
561 |
}
|
562 |
}
|
563 |
|
564 |
+
if (!\is_object($object)) {
|
565 |
if ($isDefinedTest) {
|
566 |
return false;
|
567 |
}
|
572 |
|
573 |
if (null === $object) {
|
574 |
$message = sprintf('Impossible to invoke a method ("%s") on a null variable.', $item);
|
575 |
+
} elseif (\is_array($object)) {
|
576 |
$message = sprintf('Impossible to invoke a method ("%s") on an array.', $item);
|
577 |
} else {
|
578 |
+
$message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").', $item, \gettype($object), $object);
|
579 |
}
|
580 |
|
581 |
+
throw new RuntimeError($message, -1, $this->getSourceContext());
|
582 |
}
|
583 |
|
584 |
// object property
|
585 |
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
|
586 |
+
if (isset($object->$item) || \array_key_exists((string) $item, $object)) {
|
587 |
if ($isDefinedTest) {
|
588 |
return true;
|
589 |
}
|
590 |
|
591 |
+
if ($this->env->hasExtension('\Twig\Extension\SandboxExtension')) {
|
592 |
+
$this->env->getExtension('\Twig\Extension\SandboxExtension')->checkPropertyAllowed($object, $item);
|
593 |
}
|
594 |
|
595 |
return $object->$item;
|
596 |
}
|
597 |
}
|
598 |
|
599 |
+
$class = \get_class($object);
|
600 |
|
601 |
// object method
|
602 |
if (!isset(self::$cache[$class])) {
|
603 |
// get_class_methods returns all methods accessible in the scope, but we only want public ones to be accessible in templates
|
604 |
if ($object instanceof self) {
|
605 |
+
$ref = new \ReflectionClass($class);
|
606 |
$methods = [];
|
607 |
|
608 |
+
foreach ($ref->getMethods(\ReflectionMethod::IS_PUBLIC) as $refMethod) {
|
609 |
// Accessing the environment from templates is forbidden to prevent untrusted changes to the environment
|
610 |
if ('getenvironment' !== strtolower($refMethod->name)) {
|
611 |
$methods[] = $refMethod->name;
|
663 |
return;
|
664 |
}
|
665 |
|
666 |
+
throw new RuntimeError(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());
|
667 |
}
|
668 |
|
669 |
if ($isDefinedTest) {
|
670 |
return true;
|
671 |
}
|
672 |
|
673 |
+
if ($this->env->hasExtension('\Twig\Extension\SandboxExtension')) {
|
674 |
+
$this->env->getExtension('\Twig\Extension\SandboxExtension')->checkMethodAllowed($object, $method);
|
675 |
}
|
676 |
|
677 |
// Some objects throw exceptions when they have __call, and the method we try
|
680 |
if (!$arguments) {
|
681 |
$ret = $object->$method();
|
682 |
} else {
|
683 |
+
$ret = \call_user_func_array([$object, $method], $arguments);
|
684 |
}
|
685 |
+
} catch (\BadMethodCallException $e) {
|
686 |
if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) {
|
687 |
return;
|
688 |
}
|
702 |
}
|
703 |
@trigger_error($message, E_USER_DEPRECATED);
|
704 |
|
705 |
+
return '' === $ret ? '' : new Markup($ret, $this->env->getCharset());
|
706 |
}
|
707 |
|
708 |
return $ret;
|
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
|
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 |
}
|
vendor/twig/twig/lib/Twig/TemplateWrapper.php
CHANGED
@@ -9,6 +9,10 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Exposes a template to userland.
|
14 |
*
|
@@ -21,11 +25,11 @@ final class Twig_TemplateWrapper
|
|
21 |
|
22 |
/**
|
23 |
* This method is for internal use only and should never be called
|
24 |
-
* directly (use
|
25 |
*
|
26 |
* @internal
|
27 |
*/
|
28 |
-
public function __construct(
|
29 |
{
|
30 |
$this->env = $env;
|
31 |
$this->template = $template;
|
@@ -42,7 +46,7 @@ final class Twig_TemplateWrapper
|
|
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 |
/**
|
@@ -54,7 +58,7 @@ final class Twig_TemplateWrapper
|
|
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 |
/**
|
@@ -97,13 +101,13 @@ final class Twig_TemplateWrapper
|
|
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 |
}
|
@@ -126,7 +130,7 @@ final class Twig_TemplateWrapper
|
|
126 |
}
|
127 |
|
128 |
/**
|
129 |
-
* @return
|
130 |
*/
|
131 |
public function getSourceContext()
|
132 |
{
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Environment;
|
13 |
+
use Twig\Source;
|
14 |
+
use Twig\Template;
|
15 |
+
|
16 |
/**
|
17 |
* Exposes a template to userland.
|
18 |
*
|
25 |
|
26 |
/**
|
27 |
* This method is for internal use only and should never be called
|
28 |
+
* directly (use Twig\Environment::load() instead).
|
29 |
*
|
30 |
* @internal
|
31 |
*/
|
32 |
+
public function __construct(Environment $env, Template $template)
|
33 |
{
|
34 |
$this->env = $env;
|
35 |
$this->template = $template;
|
46 |
{
|
47 |
// using func_get_args() allows to not expose the blocks argument
|
48 |
// as it should only be used by internal code
|
49 |
+
return $this->template->render($context, \func_num_args() > 1 ? func_get_arg(1) : []);
|
50 |
}
|
51 |
|
52 |
/**
|
58 |
{
|
59 |
// using func_get_args() allows to not expose the blocks argument
|
60 |
// as it should only be used by internal code
|
61 |
+
$this->template->display($context, \func_num_args() >= 1 ? func_get_arg(1) : []);
|
62 |
}
|
63 |
|
64 |
/**
|
101 |
ob_start();
|
102 |
try {
|
103 |
$this->template->displayBlock($name, $context);
|
104 |
+
} catch (\Exception $e) {
|
105 |
while (ob_get_level() > $level) {
|
106 |
ob_end_clean();
|
107 |
}
|
108 |
|
109 |
throw $e;
|
110 |
+
} catch (\Throwable $e) {
|
111 |
while (ob_get_level() > $level) {
|
112 |
ob_end_clean();
|
113 |
}
|
130 |
}
|
131 |
|
132 |
/**
|
133 |
+
* @return Source
|
134 |
*/
|
135 |
public function getSourceContext()
|
136 |
{
|
vendor/twig/twig/lib/Twig/Test/IntegrationTestCase.php
CHANGED
@@ -10,6 +10,16 @@
|
|
10 |
*/
|
11 |
|
12 |
use PHPUnit\Framework\TestCase;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
/**
|
15 |
* Integration test helper.
|
@@ -25,7 +35,7 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase
|
|
25 |
abstract protected function getFixturesDir();
|
26 |
|
27 |
/**
|
28 |
-
* @return
|
29 |
*/
|
30 |
protected function getRuntimeLoaders()
|
31 |
{
|
@@ -33,7 +43,7 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase
|
|
33 |
}
|
34 |
|
35 |
/**
|
36 |
-
* @return
|
37 |
*/
|
38 |
protected function getExtensions()
|
39 |
{
|
@@ -41,7 +51,7 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase
|
|
41 |
}
|
42 |
|
43 |
/**
|
44 |
-
* @return
|
45 |
*/
|
46 |
protected function getTwigFilters()
|
47 |
{
|
@@ -49,7 +59,7 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase
|
|
49 |
}
|
50 |
|
51 |
/**
|
52 |
-
* @return
|
53 |
*/
|
54 |
protected function getTwigFunctions()
|
55 |
{
|
@@ -57,7 +67,7 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase
|
|
57 |
}
|
58 |
|
59 |
/**
|
60 |
-
* @return
|
61 |
*/
|
62 |
protected function getTwigTests()
|
63 |
{
|
@@ -86,7 +96,7 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase
|
|
86 |
$fixturesDir = realpath($this->getFixturesDir());
|
87 |
$tests = [];
|
88 |
|
89 |
-
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($fixturesDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
|
90 |
if (!preg_match('/\.test$/', $file)) {
|
91 |
continue;
|
92 |
}
|
@@ -110,7 +120,7 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase
|
|
110 |
$exception = false;
|
111 |
preg_match_all('/--DATA--(.*?)(?:--CONFIG--(.*?))?--EXPECT--(.*?)(?=\-\-DATA\-\-|$)/s', $test, $outputs, PREG_SET_ORDER);
|
112 |
} else {
|
113 |
-
throw new InvalidArgumentException(sprintf('Test "%s" is not valid.', str_replace($fixturesDir.'/', '', $file)));
|
114 |
}
|
115 |
|
116 |
$tests[] = [str_replace($fixturesDir.'/', '', $file), $message, $condition, $templates, $exception, $outputs];
|
@@ -142,14 +152,14 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase
|
|
142 |
}
|
143 |
}
|
144 |
|
145 |
-
$loader = new
|
146 |
|
147 |
foreach ($outputs as $i => $match) {
|
148 |
$config = array_merge([
|
149 |
'cache' => false,
|
150 |
'strict_variables' => true,
|
151 |
], $match[2] ? eval($match[2].';') : []);
|
152 |
-
$twig = new
|
153 |
$twig->addGlobal('global', 'global');
|
154 |
foreach ($this->getRuntimeLoaders() as $runtimeLoader) {
|
155 |
$twig->addRuntimeLoader($runtimeLoader);
|
@@ -171,37 +181,37 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase
|
|
171 |
$twig->addFunction($function);
|
172 |
}
|
173 |
|
174 |
-
$p = new ReflectionProperty($twig, 'templateClassPrefix');
|
175 |
$p->setAccessible(true);
|
176 |
$p->setValue($twig, '__TwigTemplate_'.hash('sha256', uniqid(mt_rand(), true), false).'_');
|
177 |
|
178 |
try {
|
179 |
$template = $twig->loadTemplate('index.twig');
|
180 |
-
} catch (Exception $e) {
|
181 |
if (false !== $exception) {
|
182 |
$message = $e->getMessage();
|
183 |
-
$this->assertSame(trim($exception), trim(sprintf('%s: %s', get_class($e), $message)));
|
184 |
-
$last = substr($message, strlen($message) - 1);
|
185 |
$this->assertTrue('.' === $last || '?' === $last, $message, 'Exception message must end with a dot or a question mark.');
|
186 |
|
187 |
return;
|
188 |
}
|
189 |
|
190 |
-
throw new
|
191 |
}
|
192 |
|
193 |
try {
|
194 |
$output = trim($template->render(eval($match[1].';')), "\n ");
|
195 |
-
} catch (Exception $e) {
|
196 |
if (false !== $exception) {
|
197 |
-
$this->assertSame(trim($exception), trim(sprintf('%s: %s', get_class($e), $e->getMessage())));
|
198 |
|
199 |
return;
|
200 |
}
|
201 |
|
202 |
-
$e = new
|
203 |
|
204 |
-
$output = trim(sprintf('%s: %s', get_class($e), $e->getMessage()));
|
205 |
}
|
206 |
|
207 |
if (false !== $exception) {
|
@@ -218,8 +228,8 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase
|
|
218 |
foreach (array_keys($templates) as $name) {
|
219 |
echo "Template: $name\n";
|
220 |
$loader = $twig->getLoader();
|
221 |
-
if (!$loader instanceof
|
222 |
-
$source = new
|
223 |
} else {
|
224 |
$source = $loader->getSourceContext($name);
|
225 |
}
|
10 |
*/
|
11 |
|
12 |
use PHPUnit\Framework\TestCase;
|
13 |
+
use Twig\Environment;
|
14 |
+
use Twig\Error\Error;
|
15 |
+
use Twig\Extension\ExtensionInterface;
|
16 |
+
use Twig\Loader\ArrayLoader;
|
17 |
+
use Twig\Loader\SourceContextLoaderInterface;
|
18 |
+
use Twig\RuntimeLoader\RuntimeLoaderInterface;
|
19 |
+
use Twig\Source;
|
20 |
+
use Twig\TwigFilter;
|
21 |
+
use Twig\TwigFunction;
|
22 |
+
use Twig\TwigTest;
|
23 |
|
24 |
/**
|
25 |
* Integration test helper.
|
35 |
abstract protected function getFixturesDir();
|
36 |
|
37 |
/**
|
38 |
+
* @return RuntimeLoaderInterface[]
|
39 |
*/
|
40 |
protected function getRuntimeLoaders()
|
41 |
{
|
43 |
}
|
44 |
|
45 |
/**
|
46 |
+
* @return ExtensionInterface[]
|
47 |
*/
|
48 |
protected function getExtensions()
|
49 |
{
|
51 |
}
|
52 |
|
53 |
/**
|
54 |
+
* @return TwigFilter[]
|
55 |
*/
|
56 |
protected function getTwigFilters()
|
57 |
{
|
59 |
}
|
60 |
|
61 |
/**
|
62 |
+
* @return TwigFunction[]
|
63 |
*/
|
64 |
protected function getTwigFunctions()
|
65 |
{
|
67 |
}
|
68 |
|
69 |
/**
|
70 |
+
* @return TwigTest[]
|
71 |
*/
|
72 |
protected function getTwigTests()
|
73 |
{
|
96 |
$fixturesDir = realpath($this->getFixturesDir());
|
97 |
$tests = [];
|
98 |
|
99 |
+
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($fixturesDir), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
|
100 |
if (!preg_match('/\.test$/', $file)) {
|
101 |
continue;
|
102 |
}
|
120 |
$exception = false;
|
121 |
preg_match_all('/--DATA--(.*?)(?:--CONFIG--(.*?))?--EXPECT--(.*?)(?=\-\-DATA\-\-|$)/s', $test, $outputs, PREG_SET_ORDER);
|
122 |
} else {
|
123 |
+
throw new \InvalidArgumentException(sprintf('Test "%s" is not valid.', str_replace($fixturesDir.'/', '', $file)));
|
124 |
}
|
125 |
|
126 |
$tests[] = [str_replace($fixturesDir.'/', '', $file), $message, $condition, $templates, $exception, $outputs];
|
152 |
}
|
153 |
}
|
154 |
|
155 |
+
$loader = new ArrayLoader($templates);
|
156 |
|
157 |
foreach ($outputs as $i => $match) {
|
158 |
$config = array_merge([
|
159 |
'cache' => false,
|
160 |
'strict_variables' => true,
|
161 |
], $match[2] ? eval($match[2].';') : []);
|
162 |
+
$twig = new Environment($loader, $config);
|
163 |
$twig->addGlobal('global', 'global');
|
164 |
foreach ($this->getRuntimeLoaders() as $runtimeLoader) {
|
165 |
$twig->addRuntimeLoader($runtimeLoader);
|
181 |
$twig->addFunction($function);
|
182 |
}
|
183 |
|
184 |
+
$p = new \ReflectionProperty($twig, 'templateClassPrefix');
|
185 |
$p->setAccessible(true);
|
186 |
$p->setValue($twig, '__TwigTemplate_'.hash('sha256', uniqid(mt_rand(), true), false).'_');
|
187 |
|
188 |
try {
|
189 |
$template = $twig->loadTemplate('index.twig');
|
190 |
+
} catch (\Exception $e) {
|
191 |
if (false !== $exception) {
|
192 |
$message = $e->getMessage();
|
193 |
+
$this->assertSame(trim($exception), trim(sprintf('%s: %s', \get_class($e), $message)));
|
194 |
+
$last = substr($message, \strlen($message) - 1);
|
195 |
$this->assertTrue('.' === $last || '?' === $last, $message, 'Exception message must end with a dot or a question mark.');
|
196 |
|
197 |
return;
|
198 |
}
|
199 |
|
200 |
+
throw new Error(sprintf('%s: %s', \get_class($e), $e->getMessage()), -1, $file, $e);
|
201 |
}
|
202 |
|
203 |
try {
|
204 |
$output = trim($template->render(eval($match[1].';')), "\n ");
|
205 |
+
} catch (\Exception $e) {
|
206 |
if (false !== $exception) {
|
207 |
+
$this->assertSame(trim($exception), trim(sprintf('%s: %s', \get_class($e), $e->getMessage())));
|
208 |
|
209 |
return;
|
210 |
}
|
211 |
|
212 |
+
$e = new Error(sprintf('%s: %s', \get_class($e), $e->getMessage()), -1, $file, $e);
|
213 |
|
214 |
+
$output = trim(sprintf('%s: %s', \get_class($e), $e->getMessage()));
|
215 |
}
|
216 |
|
217 |
if (false !== $exception) {
|
228 |
foreach (array_keys($templates) as $name) {
|
229 |
echo "Template: $name\n";
|
230 |
$loader = $twig->getLoader();
|
231 |
+
if (!$loader instanceof SourceContextLoaderInterface) {
|
232 |
+
$source = new Source($loader->getSource($name), $name);
|
233 |
} else {
|
234 |
$source = $loader->getSourceContext($name);
|
235 |
}
|
vendor/twig/twig/lib/Twig/Test/Method.php
CHANGED
@@ -9,6 +9,8 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
12 |
@trigger_error('The Twig_Test_Method class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleTest instead.', E_USER_DEPRECATED);
|
13 |
|
14 |
/**
|
@@ -23,7 +25,7 @@ class Twig_Test_Method extends Twig_Test
|
|
23 |
protected $extension;
|
24 |
protected $method;
|
25 |
|
26 |
-
public function __construct(
|
27 |
{
|
28 |
$options['callable'] = [$extension, $method];
|
29 |
|
@@ -35,6 +37,6 @@ class Twig_Test_Method extends Twig_Test
|
|
35 |
|
36 |
public function compile()
|
37 |
{
|
38 |
-
return sprintf('$this->env->getExtension(\'%s\')->%s', get_class($this->extension), $this->method);
|
39 |
}
|
40 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Extension\ExtensionInterface;
|
13 |
+
|
14 |
@trigger_error('The Twig_Test_Method class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleTest instead.', E_USER_DEPRECATED);
|
15 |
|
16 |
/**
|
25 |
protected $extension;
|
26 |
protected $method;
|
27 |
|
28 |
+
public function __construct(ExtensionInterface $extension, $method, array $options = [])
|
29 |
{
|
30 |
$options['callable'] = [$extension, $method];
|
31 |
|
37 |
|
38 |
public function compile()
|
39 |
{
|
40 |
+
return sprintf('$this->env->getExtension(\'%s\')->%s', \get_class($this->extension), $this->method);
|
41 |
}
|
42 |
}
|
vendor/twig/twig/lib/Twig/Test/NodeTestCase.php
CHANGED
@@ -10,6 +10,10 @@
|
|
10 |
*/
|
11 |
|
12 |
use PHPUnit\Framework\TestCase;
|
|
|
|
|
|
|
|
|
13 |
|
14 |
abstract class Twig_Test_NodeTestCase extends TestCase
|
15 |
{
|
@@ -23,7 +27,7 @@ abstract class Twig_Test_NodeTestCase extends TestCase
|
|
23 |
$this->assertNodeCompilation($source, $node, $environment, $isPattern);
|
24 |
}
|
25 |
|
26 |
-
public function assertNodeCompilation($source,
|
27 |
{
|
28 |
$compiler = $this->getCompiler($environment);
|
29 |
$compiler->compile($node);
|
@@ -35,14 +39,14 @@ abstract class Twig_Test_NodeTestCase extends TestCase
|
|
35 |
}
|
36 |
}
|
37 |
|
38 |
-
protected function getCompiler(
|
39 |
{
|
40 |
-
return new
|
41 |
}
|
42 |
|
43 |
protected function getEnvironment()
|
44 |
{
|
45 |
-
return new
|
46 |
}
|
47 |
|
48 |
protected function getVariableGetter($name, $line = false)
|
@@ -62,7 +66,7 @@ abstract class Twig_Test_NodeTestCase extends TestCase
|
|
62 |
|
63 |
protected function getAttributeGetter()
|
64 |
{
|
65 |
-
if (function_exists('twig_template_get_attributes')) {
|
66 |
return 'twig_template_get_attributes($this, ';
|
67 |
}
|
68 |
|
10 |
*/
|
11 |
|
12 |
use PHPUnit\Framework\TestCase;
|
13 |
+
use Twig\Compiler;
|
14 |
+
use Twig\Environment;
|
15 |
+
use Twig\Loader\ArrayLoader;
|
16 |
+
use Twig\Node\Node;
|
17 |
|
18 |
abstract class Twig_Test_NodeTestCase extends TestCase
|
19 |
{
|
27 |
$this->assertNodeCompilation($source, $node, $environment, $isPattern);
|
28 |
}
|
29 |
|
30 |
+
public function assertNodeCompilation($source, Node $node, Environment $environment = null, $isPattern = false)
|
31 |
{
|
32 |
$compiler = $this->getCompiler($environment);
|
33 |
$compiler->compile($node);
|
39 |
}
|
40 |
}
|
41 |
|
42 |
+
protected function getCompiler(Environment $environment = null)
|
43 |
{
|
44 |
+
return new Compiler(null === $environment ? $this->getEnvironment() : $environment);
|
45 |
}
|
46 |
|
47 |
protected function getEnvironment()
|
48 |
{
|
49 |
+
return new Environment(new ArrayLoader([]));
|
50 |
}
|
51 |
|
52 |
protected function getVariableGetter($name, $line = false)
|
66 |
|
67 |
protected function getAttributeGetter()
|
68 |
{
|
69 |
+
if (\function_exists('twig_template_get_attributes')) {
|
70 |
return 'twig_template_get_attributes($this, ';
|
71 |
}
|
72 |
|
vendor/twig/twig/lib/Twig/Token.php
CHANGED
@@ -69,14 +69,14 @@ class Twig_Token
|
|
69 |
*/
|
70 |
public function test($type, $values = null)
|
71 |
{
|
72 |
-
if (null === $values &&
|
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 |
}
|
@@ -156,10 +156,10 @@ class Twig_Token
|
|
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 : '
|
163 |
}
|
164 |
|
165 |
/**
|
@@ -199,7 +199,7 @@ class Twig_Token
|
|
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 |
}
|
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 |
}
|
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 |
/**
|
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 |
}
|
vendor/twig/twig/lib/Twig/TokenParser.php
CHANGED
@@ -9,12 +9,15 @@
|
|
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
|
18 |
{
|
19 |
/**
|
20 |
* @var Twig_Parser
|
@@ -24,7 +27,7 @@ abstract class Twig_TokenParser implements Twig_TokenParserInterface
|
|
24 |
/**
|
25 |
* Sets the parser associated with this token parser.
|
26 |
*/
|
27 |
-
public function setParser(
|
28 |
{
|
29 |
$this->parser = $parser;
|
30 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Parser;
|
13 |
+
use Twig\TokenParser\TokenParserInterface;
|
14 |
+
|
15 |
/**
|
16 |
* Base class for all token parsers.
|
17 |
*
|
18 |
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
*/
|
20 |
+
abstract class Twig_TokenParser implements TokenParserInterface
|
21 |
{
|
22 |
/**
|
23 |
* @var Twig_Parser
|
27 |
/**
|
28 |
* Sets the parser associated with this token parser.
|
29 |
*/
|
30 |
+
public function setParser(Parser $parser)
|
31 |
{
|
32 |
$this->parser = $parser;
|
33 |
}
|
vendor/twig/twig/lib/Twig/TokenParser/AutoEscape.php
CHANGED
@@ -9,39 +9,43 @@
|
|
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 |
-
*
|
16 |
-
*
|
17 |
-
*
|
18 |
-
* {% endautoescape %}
|
19 |
*
|
20 |
-
*
|
21 |
-
*
|
22 |
-
*
|
23 |
*
|
24 |
-
*
|
25 |
-
*
|
26 |
-
*
|
27 |
-
*
|
28 |
-
* </pre>
|
29 |
*
|
30 |
* @final
|
31 |
*/
|
32 |
-
class Twig_TokenParser_AutoEscape extends
|
33 |
{
|
34 |
-
public function parse(
|
35 |
{
|
36 |
$lineno = $token->getLine();
|
37 |
$stream = $this->parser->getStream();
|
38 |
|
39 |
-
if ($stream->test(
|
40 |
$value = 'html';
|
41 |
} else {
|
42 |
$expr = $this->parser->getExpressionParser()->parseExpression();
|
43 |
-
if (!$expr instanceof
|
44 |
-
throw new
|
45 |
}
|
46 |
$value = $expr->getAttribute('value');
|
47 |
|
@@ -51,25 +55,25 @@ class Twig_TokenParser_AutoEscape extends Twig_TokenParser
|
|
51 |
$value = 'html';
|
52 |
}
|
53 |
|
54 |
-
if ($compat && $stream->test(
|
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
|
59 |
}
|
60 |
|
61 |
$value = $stream->next()->getValue();
|
62 |
}
|
63 |
}
|
64 |
|
65 |
-
$stream->expect(
|
66 |
$body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
|
67 |
-
$stream->expect(
|
68 |
|
69 |
-
return new
|
70 |
}
|
71 |
|
72 |
-
public function decideBlockEnd(
|
73 |
{
|
74 |
return $token->test('endautoescape');
|
75 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Error\SyntaxError;
|
13 |
+
use Twig\Node\AutoEscapeNode;
|
14 |
+
use Twig\Node\Expression\ConstantExpression;
|
15 |
+
use Twig\Token;
|
16 |
+
use Twig\TokenParser\AbstractTokenParser;
|
17 |
+
|
18 |
/**
|
19 |
* Marks a section of a template to be escaped or not.
|
20 |
*
|
21 |
+
* {% autoescape true %}
|
22 |
+
* Everything will be automatically escaped in this block
|
23 |
+
* {% endautoescape %}
|
|
|
24 |
*
|
25 |
+
* {% autoescape false %}
|
26 |
+
* Everything will be outputed as is in this block
|
27 |
+
* {% endautoescape %}
|
28 |
*
|
29 |
+
* {% autoescape true js %}
|
30 |
+
* Everything will be automatically escaped in this block
|
31 |
+
* using the js escaping strategy
|
32 |
+
* {% endautoescape %}
|
|
|
33 |
*
|
34 |
* @final
|
35 |
*/
|
36 |
+
class Twig_TokenParser_AutoEscape extends AbstractTokenParser
|
37 |
{
|
38 |
+
public function parse(Token $token)
|
39 |
{
|
40 |
$lineno = $token->getLine();
|
41 |
$stream = $this->parser->getStream();
|
42 |
|
43 |
+
if ($stream->test(Token::BLOCK_END_TYPE)) {
|
44 |
$value = 'html';
|
45 |
} else {
|
46 |
$expr = $this->parser->getExpressionParser()->parseExpression();
|
47 |
+
if (!$expr instanceof ConstantExpression) {
|
48 |
+
throw new SyntaxError('An escaping strategy must be a string or a bool.', $stream->getCurrent()->getLine(), $stream->getSourceContext());
|
49 |
}
|
50 |
$value = $expr->getAttribute('value');
|
51 |
|
55 |
$value = 'html';
|
56 |
}
|
57 |
|
58 |
+
if ($compat && $stream->test(Token::NAME_TYPE)) {
|
59 |
@trigger_error('Using the autoescape tag with "true" or "false" before the strategy name is deprecated since version 1.21.', E_USER_DEPRECATED);
|
60 |
|
61 |
if (false === $value) {
|
62 |
+
throw new SyntaxError('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->getSourceContext());
|
63 |
}
|
64 |
|
65 |
$value = $stream->next()->getValue();
|
66 |
}
|
67 |
}
|
68 |
|
69 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
70 |
$body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
|
71 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
72 |
|
73 |
+
return new AutoEscapeNode($value, $body, $lineno, $this->getTag());
|
74 |
}
|
75 |
|
76 |
+
public function decideBlockEnd(Token $token)
|
77 |
{
|
78 |
return $token->test('endautoescape');
|
79 |
}
|
vendor/twig/twig/lib/Twig/TokenParser/Block.php
CHANGED
@@ -10,56 +10,62 @@
|
|
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
|
26 |
{
|
27 |
-
public function parse(
|
28 |
{
|
29 |
$lineno = $token->getLine();
|
30 |
$stream = $this->parser->getStream();
|
31 |
-
$name = $stream->expect(
|
32 |
if ($this->parser->hasBlock($name)) {
|
33 |
-
throw new
|
34 |
}
|
35 |
-
$this->parser->setBlock($name, $block = new
|
36 |
$this->parser->pushLocalScope();
|
37 |
$this->parser->pushBlockStack($name);
|
38 |
|
39 |
-
if ($stream->nextIf(
|
40 |
$body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
|
41 |
-
if ($token = $stream->nextIf(
|
42 |
$value = $token->getValue();
|
43 |
|
44 |
if ($value != $name) {
|
45 |
-
throw new
|
46 |
}
|
47 |
}
|
48 |
} else {
|
49 |
-
$body = new
|
50 |
-
new
|
51 |
]);
|
52 |
}
|
53 |
-
$stream->expect(
|
54 |
|
55 |
$block->setNode('body', $body);
|
56 |
$this->parser->popBlockStack();
|
57 |
$this->parser->popLocalScope();
|
58 |
|
59 |
-
return new
|
60 |
}
|
61 |
|
62 |
-
public function decideBlockEnd(
|
63 |
{
|
64 |
return $token->test('endblock');
|
65 |
}
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Error\SyntaxError;
|
14 |
+
use Twig\Node\BlockNode;
|
15 |
+
use Twig\Node\BlockReferenceNode;
|
16 |
+
use Twig\Node\Node;
|
17 |
+
use Twig\Node\PrintNode;
|
18 |
+
use Twig\Token;
|
19 |
+
use Twig\TokenParser\AbstractTokenParser;
|
20 |
+
|
21 |
/**
|
22 |
* Marks a section of a template as being reusable.
|
23 |
*
|
|
|
24 |
* {% block head %}
|
25 |
* <link rel="stylesheet" href="style.css" />
|
26 |
* <title>{% block title %}{% endblock %} - My Webpage</title>
|
27 |
* {% endblock %}
|
|
|
28 |
*
|
29 |
* @final
|
30 |
*/
|
31 |
+
class Twig_TokenParser_Block extends AbstractTokenParser
|
32 |
{
|
33 |
+
public function parse(Token $token)
|
34 |
{
|
35 |
$lineno = $token->getLine();
|
36 |
$stream = $this->parser->getStream();
|
37 |
+
$name = $stream->expect(Token::NAME_TYPE)->getValue();
|
38 |
if ($this->parser->hasBlock($name)) {
|
39 |
+
throw new SyntaxError(sprintf("The block '%s' has already been defined line %d.", $name, $this->parser->getBlock($name)->getTemplateLine()), $stream->getCurrent()->getLine(), $stream->getSourceContext());
|
40 |
}
|
41 |
+
$this->parser->setBlock($name, $block = new BlockNode($name, new Node([]), $lineno));
|
42 |
$this->parser->pushLocalScope();
|
43 |
$this->parser->pushBlockStack($name);
|
44 |
|
45 |
+
if ($stream->nextIf(Token::BLOCK_END_TYPE)) {
|
46 |
$body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
|
47 |
+
if ($token = $stream->nextIf(Token::NAME_TYPE)) {
|
48 |
$value = $token->getValue();
|
49 |
|
50 |
if ($value != $name) {
|
51 |
+
throw new SyntaxError(sprintf('Expected endblock for block "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext());
|
52 |
}
|
53 |
}
|
54 |
} else {
|
55 |
+
$body = new Node([
|
56 |
+
new PrintNode($this->parser->getExpressionParser()->parseExpression(), $lineno),
|
57 |
]);
|
58 |
}
|
59 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
60 |
|
61 |
$block->setNode('body', $body);
|
62 |
$this->parser->popBlockStack();
|
63 |
$this->parser->popLocalScope();
|
64 |
|
65 |
+
return new BlockReferenceNode($name, $lineno, $this->getTag());
|
66 |
}
|
67 |
|
68 |
+
public function decideBlockEnd(Token $token)
|
69 |
{
|
70 |
return $token->test('endblock');
|
71 |
}
|
vendor/twig/twig/lib/Twig/TokenParser/Deprecated.php
CHANGED
@@ -9,28 +9,29 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Deprecates a section of a template.
|
14 |
*
|
15 |
-
*
|
16 |
-
*
|
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
|
26 |
{
|
27 |
-
public function parse(
|
28 |
{
|
29 |
$expr = $this->parser->getExpressionParser()->parseExpression();
|
30 |
|
31 |
-
$this->parser->getStream()->expect(
|
32 |
|
33 |
-
return new
|
34 |
}
|
35 |
|
36 |
public function getTag()
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Node\DeprecatedNode;
|
13 |
+
use Twig\Token;
|
14 |
+
use Twig\TokenParser\AbstractTokenParser;
|
15 |
+
|
16 |
/**
|
17 |
* Deprecates a section of a template.
|
18 |
*
|
19 |
+
* {% deprecated 'The "base.twig" template is deprecated, use "layout.twig" instead.' %}
|
20 |
+
* {% extends 'layout.html.twig' %}
|
|
|
|
|
|
|
21 |
*
|
22 |
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
23 |
*
|
24 |
* @final
|
25 |
*/
|
26 |
+
class Twig_TokenParser_Deprecated extends AbstractTokenParser
|
27 |
{
|
28 |
+
public function parse(Token $token)
|
29 |
{
|
30 |
$expr = $this->parser->getExpressionParser()->parseExpression();
|
31 |
|
32 |
+
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
33 |
|
34 |
+
return new DeprecatedNode($expr, $token->getLine(), $this->getTag());
|
35 |
}
|
36 |
|
37 |
public function getTag()
|
vendor/twig/twig/lib/Twig/TokenParser/Do.php
CHANGED
@@ -9,20 +9,24 @@
|
|
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
|
18 |
{
|
19 |
-
public function parse(
|
20 |
{
|
21 |
$expr = $this->parser->getExpressionParser()->parseExpression();
|
22 |
|
23 |
-
$this->parser->getStream()->expect(
|
24 |
|
25 |
-
return new
|
26 |
}
|
27 |
|
28 |
public function getTag()
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Node\DoNode;
|
13 |
+
use Twig\Token;
|
14 |
+
use Twig\TokenParser\AbstractTokenParser;
|
15 |
+
|
16 |
/**
|
17 |
* Evaluates an expression, discarding the returned value.
|
18 |
*
|
19 |
* @final
|
20 |
*/
|
21 |
+
class Twig_TokenParser_Do extends AbstractTokenParser
|
22 |
{
|
23 |
+
public function parse(Token $token)
|
24 |
{
|
25 |
$expr = $this->parser->getExpressionParser()->parseExpression();
|
26 |
|
27 |
+
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
28 |
|
29 |
+
return new DoNode($expr, $token->getLine(), $this->getTag());
|
30 |
}
|
31 |
|
32 |
public function getTag()
|
vendor/twig/twig/lib/Twig/TokenParser/Embed.php
CHANGED
@@ -9,14 +9,20 @@
|
|
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
|
18 |
{
|
19 |
-
public function parse(
|
20 |
{
|
21 |
$stream = $this->parser->getStream();
|
22 |
|
@@ -24,19 +30,19 @@ class Twig_TokenParser_Embed extends Twig_TokenParser_Include
|
|
24 |
|
25 |
list($variables, $only, $ignoreMissing) = $this->parseArguments();
|
26 |
|
27 |
-
$parentToken = $fakeParentToken = new
|
28 |
-
if ($parent instanceof
|
29 |
-
$parentToken = new
|
30 |
-
} elseif ($parent instanceof
|
31 |
-
$parentToken = new
|
32 |
}
|
33 |
|
34 |
// inject a fake parent to make the parent() function work
|
35 |
$stream->injectTokens([
|
36 |
-
new
|
37 |
-
new
|
38 |
$parentToken,
|
39 |
-
new
|
40 |
]);
|
41 |
|
42 |
$module = $this->parser->parse($stream, [$this, 'decideBlockEnd'], true);
|
@@ -48,12 +54,12 @@ class Twig_TokenParser_Embed extends Twig_TokenParser_Include
|
|
48 |
|
49 |
$this->parser->embedTemplate($module);
|
50 |
|
51 |
-
$stream->expect(
|
52 |
|
53 |
-
return new
|
54 |
}
|
55 |
|
56 |
-
public function decideBlockEnd(
|
57 |
{
|
58 |
return $token->test('endembed');
|
59 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Node\EmbedNode;
|
13 |
+
use Twig\Node\Expression\ConstantExpression;
|
14 |
+
use Twig\Node\Expression\NameExpression;
|
15 |
+
use Twig\Token;
|
16 |
+
use Twig\TokenParser\IncludeTokenParser;
|
17 |
+
|
18 |
/**
|
19 |
* Embeds a template.
|
20 |
*
|
21 |
* @final
|
22 |
*/
|
23 |
+
class Twig_TokenParser_Embed extends IncludeTokenParser
|
24 |
{
|
25 |
+
public function parse(Token $token)
|
26 |
{
|
27 |
$stream = $this->parser->getStream();
|
28 |
|
30 |
|
31 |
list($variables, $only, $ignoreMissing) = $this->parseArguments();
|
32 |
|
33 |
+
$parentToken = $fakeParentToken = new Token(Token::STRING_TYPE, '__parent__', $token->getLine());
|
34 |
+
if ($parent instanceof ConstantExpression) {
|
35 |
+
$parentToken = new Token(Token::STRING_TYPE, $parent->getAttribute('value'), $token->getLine());
|
36 |
+
} elseif ($parent instanceof NameExpression) {
|
37 |
+
$parentToken = new Token(Token::NAME_TYPE, $parent->getAttribute('name'), $token->getLine());
|
38 |
}
|
39 |
|
40 |
// inject a fake parent to make the parent() function work
|
41 |
$stream->injectTokens([
|
42 |
+
new Token(Token::BLOCK_START_TYPE, '', $token->getLine()),
|
43 |
+
new Token(Token::NAME_TYPE, 'extends', $token->getLine()),
|
44 |
$parentToken,
|
45 |
+
new Token(Token::BLOCK_END_TYPE, '', $token->getLine()),
|
46 |
]);
|
47 |
|
48 |
$module = $this->parser->parse($stream, [$this, 'decideBlockEnd'], true);
|
54 |
|
55 |
$this->parser->embedTemplate($module);
|
56 |
|
57 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
58 |
|
59 |
+
return new EmbedNode($module->getTemplateName(), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
|
60 |
}
|
61 |
|
62 |
+
public function decideBlockEnd(Token $token)
|
63 |
{
|
64 |
return $token->test('endembed');
|
65 |
}
|
vendor/twig/twig/lib/Twig/TokenParser/Extends.php
CHANGED
@@ -10,31 +10,33 @@
|
|
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
|
23 |
{
|
24 |
-
public function parse(
|
25 |
{
|
26 |
$stream = $this->parser->getStream();
|
27 |
|
28 |
if (!$this->parser->isMainScope()) {
|
29 |
-
throw new
|
30 |
}
|
31 |
|
32 |
if (null !== $this->parser->getParent()) {
|
33 |
-
throw new
|
34 |
}
|
35 |
$this->parser->setParent($this->parser->getExpressionParser()->parseExpression());
|
36 |
|
37 |
-
$stream->expect(
|
38 |
}
|
39 |
|
40 |
public function getTag()
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Error\SyntaxError;
|
14 |
+
use Twig\Token;
|
15 |
+
use Twig\TokenParser\AbstractTokenParser;
|
16 |
+
|
17 |
/**
|
18 |
* Extends a template by another one.
|
19 |
*
|
|
|
20 |
* {% extends "base.html" %}
|
|
|
21 |
*
|
22 |
* @final
|
23 |
*/
|
24 |
+
class Twig_TokenParser_Extends extends AbstractTokenParser
|
25 |
{
|
26 |
+
public function parse(Token $token)
|
27 |
{
|
28 |
$stream = $this->parser->getStream();
|
29 |
|
30 |
if (!$this->parser->isMainScope()) {
|
31 |
+
throw new SyntaxError('Cannot extend from a block.', $token->getLine(), $stream->getSourceContext());
|
32 |
}
|
33 |
|
34 |
if (null !== $this->parser->getParent()) {
|
35 |
+
throw new SyntaxError('Multiple extends tags are forbidden.', $token->getLine(), $stream->getSourceContext());
|
36 |
}
|
37 |
$this->parser->setParent($this->parser->getExpressionParser()->parseExpression());
|
38 |
|
39 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
40 |
}
|
41 |
|
42 |
public function getTag()
|
vendor/twig/twig/lib/Twig/TokenParser/Filter.php
CHANGED
@@ -9,37 +9,42 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Filters a section of a template by applying filters.
|
14 |
*
|
15 |
-
*
|
16 |
-
*
|
17 |
-
*
|
18 |
-
* {% endfilter %}
|
19 |
-
* </pre>
|
20 |
*
|
21 |
* @final
|
22 |
*/
|
23 |
-
class Twig_TokenParser_Filter extends
|
24 |
{
|
25 |
-
public function parse(
|
26 |
{
|
27 |
$name = $this->parser->getVarName();
|
28 |
-
$ref = new
|
29 |
|
30 |
$filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag());
|
31 |
-
$this->parser->getStream()->expect(
|
32 |
|
33 |
$body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
|
34 |
-
$this->parser->getStream()->expect(
|
35 |
|
36 |
-
$block = new
|
37 |
$this->parser->setBlock($name, $block);
|
38 |
|
39 |
-
return new
|
40 |
}
|
41 |
|
42 |
-
public function decideBlockEnd(
|
43 |
{
|
44 |
return $token->test('endfilter');
|
45 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Node\BlockNode;
|
13 |
+
use Twig\Node\Expression\BlockReferenceExpression;
|
14 |
+
use Twig\Node\Expression\ConstantExpression;
|
15 |
+
use Twig\Node\PrintNode;
|
16 |
+
use Twig\Token;
|
17 |
+
use Twig\TokenParser\AbstractTokenParser;
|
18 |
+
|
19 |
/**
|
20 |
* Filters a section of a template by applying filters.
|
21 |
*
|
22 |
+
* {% filter upper %}
|
23 |
+
* This text becomes uppercase
|
24 |
+
* {% endfilter %}
|
|
|
|
|
25 |
*
|
26 |
* @final
|
27 |
*/
|
28 |
+
class Twig_TokenParser_Filter extends AbstractTokenParser
|
29 |
{
|
30 |
+
public function parse(Token $token)
|
31 |
{
|
32 |
$name = $this->parser->getVarName();
|
33 |
+
$ref = new BlockReferenceExpression(new ConstantExpression($name, $token->getLine()), null, $token->getLine(), $this->getTag());
|
34 |
|
35 |
$filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag());
|
36 |
+
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
37 |
|
38 |
$body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
|
39 |
+
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
40 |
|
41 |
+
$block = new BlockNode($name, $body, $token->getLine());
|
42 |
$this->parser->setBlock($name, $block);
|
43 |
|
44 |
+
return new PrintNode($filter, $token->getLine(), $this->getTag());
|
45 |
}
|
46 |
|
47 |
+
public function decideBlockEnd(Token $token)
|
48 |
{
|
49 |
return $token->test('endfilter');
|
50 |
}
|
vendor/twig/twig/lib/Twig/TokenParser/Flush.php
CHANGED
@@ -9,6 +9,10 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Flushes the output to the client.
|
14 |
*
|
@@ -16,13 +20,13 @@
|
|
16 |
*
|
17 |
* @final
|
18 |
*/
|
19 |
-
class Twig_TokenParser_Flush extends
|
20 |
{
|
21 |
-
public function parse(
|
22 |
{
|
23 |
-
$this->parser->getStream()->expect(
|
24 |
|
25 |
-
return new
|
26 |
}
|
27 |
|
28 |
public function getTag()
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Node\FlushNode;
|
13 |
+
use Twig\Token;
|
14 |
+
use Twig\TokenParser\AbstractTokenParser;
|
15 |
+
|
16 |
/**
|
17 |
* Flushes the output to the client.
|
18 |
*
|
20 |
*
|
21 |
* @final
|
22 |
*/
|
23 |
+
class Twig_TokenParser_Flush extends AbstractTokenParser
|
24 |
{
|
25 |
+
public function parse(Token $token)
|
26 |
{
|
27 |
+
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
28 |
|
29 |
+
return new FlushNode($token->getLine(), $this->getTag());
|
30 |
}
|
31 |
|
32 |
public function getTag()
|
vendor/twig/twig/lib/Twig/TokenParser/For.php
CHANGED
@@ -10,53 +10,61 @@
|
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
/**
|
14 |
* Loops over each item of a sequence.
|
15 |
*
|
16 |
-
*
|
17 |
-
*
|
18 |
-
*
|
19 |
-
*
|
20 |
-
*
|
21 |
-
* </ul>
|
22 |
-
* </pre>
|
23 |
*
|
24 |
* @final
|
25 |
*/
|
26 |
-
class Twig_TokenParser_For extends
|
27 |
{
|
28 |
-
public function parse(
|
29 |
{
|
30 |
$lineno = $token->getLine();
|
31 |
$stream = $this->parser->getStream();
|
32 |
$targets = $this->parser->getExpressionParser()->parseAssignmentExpression();
|
33 |
-
$stream->expect(
|
34 |
$seq = $this->parser->getExpressionParser()->parseExpression();
|
35 |
|
36 |
$ifexpr = null;
|
37 |
-
if ($stream->nextIf(
|
38 |
$ifexpr = $this->parser->getExpressionParser()->parseExpression();
|
39 |
}
|
40 |
|
41 |
-
$stream->expect(
|
42 |
$body = $this->parser->subparse([$this, 'decideForFork']);
|
43 |
if ('else' == $stream->next()->getValue()) {
|
44 |
-
$stream->expect(
|
45 |
$else = $this->parser->subparse([$this, 'decideForEnd'], true);
|
46 |
} else {
|
47 |
$else = null;
|
48 |
}
|
49 |
-
$stream->expect(
|
50 |
|
51 |
-
if (count($targets) > 1) {
|
52 |
$keyTarget = $targets->getNode(0);
|
53 |
-
$keyTarget = new
|
54 |
$valueTarget = $targets->getNode(1);
|
55 |
-
$valueTarget = new
|
56 |
} else {
|
57 |
-
$keyTarget = new
|
58 |
$valueTarget = $targets->getNode(0);
|
59 |
-
$valueTarget = new
|
60 |
}
|
61 |
|
62 |
if ($ifexpr) {
|
@@ -64,24 +72,24 @@ class Twig_TokenParser_For extends Twig_TokenParser
|
|
64 |
$this->checkLoopUsageBody($stream, $body);
|
65 |
}
|
66 |
|
67 |
-
return new
|
68 |
}
|
69 |
|
70 |
-
public function decideForFork(
|
71 |
{
|
72 |
return $token->test(['else', 'endfor']);
|
73 |
}
|
74 |
|
75 |
-
public function decideForEnd(
|
76 |
{
|
77 |
return $token->test('endfor');
|
78 |
}
|
79 |
|
80 |
// the loop variable cannot be used in the condition
|
81 |
-
protected function checkLoopUsageCondition(
|
82 |
{
|
83 |
-
if ($node instanceof
|
84 |
-
throw new
|
85 |
}
|
86 |
|
87 |
foreach ($node as $n) {
|
@@ -95,17 +103,17 @@ class Twig_TokenParser_For extends Twig_TokenParser
|
|
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(
|
99 |
{
|
100 |
-
if ($node instanceof
|
101 |
$attribute = $node->getNode('attribute');
|
102 |
-
if ($attribute instanceof
|
103 |
-
throw new
|
104 |
}
|
105 |
}
|
106 |
|
107 |
// should check for parent.loop.XXX usage
|
108 |
-
if ($node instanceof
|
109 |
return;
|
110 |
}
|
111 |
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Error\SyntaxError;
|
14 |
+
use Twig\Node\Expression\AssignNameExpression;
|
15 |
+
use Twig\Node\Expression\ConstantExpression;
|
16 |
+
use Twig\Node\Expression\GetAttrExpression;
|
17 |
+
use Twig\Node\Expression\NameExpression;
|
18 |
+
use Twig\Node\ForNode;
|
19 |
+
use Twig\Token;
|
20 |
+
use Twig\TokenParser\AbstractTokenParser;
|
21 |
+
use Twig\TokenStream;
|
22 |
+
|
23 |
/**
|
24 |
* Loops over each item of a sequence.
|
25 |
*
|
26 |
+
* <ul>
|
27 |
+
* {% for user in users %}
|
28 |
+
* <li>{{ user.username|e }}</li>
|
29 |
+
* {% endfor %}
|
30 |
+
* </ul>
|
|
|
|
|
31 |
*
|
32 |
* @final
|
33 |
*/
|
34 |
+
class Twig_TokenParser_For extends AbstractTokenParser
|
35 |
{
|
36 |
+
public function parse(Token $token)
|
37 |
{
|
38 |
$lineno = $token->getLine();
|
39 |
$stream = $this->parser->getStream();
|
40 |
$targets = $this->parser->getExpressionParser()->parseAssignmentExpression();
|
41 |
+
$stream->expect(Token::OPERATOR_TYPE, 'in');
|
42 |
$seq = $this->parser->getExpressionParser()->parseExpression();
|
43 |
|
44 |
$ifexpr = null;
|
45 |
+
if ($stream->nextIf(Token::NAME_TYPE, 'if')) {
|
46 |
$ifexpr = $this->parser->getExpressionParser()->parseExpression();
|
47 |
}
|
48 |
|
49 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
50 |
$body = $this->parser->subparse([$this, 'decideForFork']);
|
51 |
if ('else' == $stream->next()->getValue()) {
|
52 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
53 |
$else = $this->parser->subparse([$this, 'decideForEnd'], true);
|
54 |
} else {
|
55 |
$else = null;
|
56 |
}
|
57 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
58 |
|
59 |
+
if (\count($targets) > 1) {
|
60 |
$keyTarget = $targets->getNode(0);
|
61 |
+
$keyTarget = new AssignNameExpression($keyTarget->getAttribute('name'), $keyTarget->getTemplateLine());
|
62 |
$valueTarget = $targets->getNode(1);
|
63 |
+
$valueTarget = new AssignNameExpression($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine());
|
64 |
} else {
|
65 |
+
$keyTarget = new AssignNameExpression('_key', $lineno);
|
66 |
$valueTarget = $targets->getNode(0);
|
67 |
+
$valueTarget = new AssignNameExpression($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine());
|
68 |
}
|
69 |
|
70 |
if ($ifexpr) {
|
72 |
$this->checkLoopUsageBody($stream, $body);
|
73 |
}
|
74 |
|
75 |
+
return new ForNode($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, $lineno, $this->getTag());
|
76 |
}
|
77 |
|
78 |
+
public function decideForFork(Token $token)
|
79 |
{
|
80 |
return $token->test(['else', 'endfor']);
|
81 |
}
|
82 |
|
83 |
+
public function decideForEnd(Token $token)
|
84 |
{
|
85 |
return $token->test('endfor');
|
86 |
}
|
87 |
|
88 |
// the loop variable cannot be used in the condition
|
89 |
+
protected function checkLoopUsageCondition(TokenStream $stream, Twig_NodeInterface $node)
|
90 |
{
|
91 |
+
if ($node instanceof GetAttrExpression && $node->getNode('node') instanceof NameExpression && 'loop' == $node->getNode('node')->getAttribute('name')) {
|
92 |
+
throw new SyntaxError('The "loop" variable cannot be used in a looping condition.', $node->getTemplateLine(), $stream->getSourceContext());
|
93 |
}
|
94 |
|
95 |
foreach ($node as $n) {
|
103 |
|
104 |
// check usage of non-defined loop-items
|
105 |
// it does not catch all problems (for instance when a for is included into another or when the variable is used in an include)
|
106 |
+
protected function checkLoopUsageBody(TokenStream $stream, Twig_NodeInterface $node)
|
107 |
{
|
108 |
+
if ($node instanceof GetAttrExpression && $node->getNode('node') instanceof NameExpression && 'loop' == $node->getNode('node')->getAttribute('name')) {
|
109 |
$attribute = $node->getNode('attribute');
|
110 |
+
if ($attribute instanceof ConstantExpression && \in_array($attribute->getAttribute('value'), ['length', 'revindex0', 'revindex', 'last'])) {
|
111 |
+
throw new SyntaxError(sprintf('The "loop.%s" variable is not defined when looping with a condition.', $attribute->getAttribute('value')), $node->getTemplateLine(), $stream->getSourceContext());
|
112 |
}
|
113 |
}
|
114 |
|
115 |
// should check for parent.loop.XXX usage
|
116 |
+
if ($node instanceof ForNode) {
|
117 |
return;
|
118 |
}
|
119 |
|
vendor/twig/twig/lib/Twig/TokenParser/From.php
CHANGED
@@ -9,18 +9,22 @@
|
|
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
|
22 |
{
|
23 |
-
public function parse(
|
24 |
{
|
25 |
$macro = $this->parser->getExpressionParser()->parseExpression();
|
26 |
$stream = $this->parser->getStream();
|
@@ -28,27 +32,27 @@ class Twig_TokenParser_From extends Twig_TokenParser
|
|
28 |
|
29 |
$targets = [];
|
30 |
do {
|
31 |
-
$name = $stream->expect(
|
32 |
|
33 |
$alias = $name;
|
34 |
if ($stream->nextIf('as')) {
|
35 |
-
$alias = $stream->expect(
|
36 |
}
|
37 |
|
38 |
$targets[$name] = $alias;
|
39 |
|
40 |
-
if (!$stream->nextIf(
|
41 |
break;
|
42 |
}
|
43 |
} while (true);
|
44 |
|
45 |
-
$stream->expect(
|
46 |
|
47 |
-
$node = new
|
48 |
|
49 |
foreach ($targets as $name => $alias) {
|
50 |
if ($this->parser->isReservedMacroName($name)) {
|
51 |
-
throw new
|
52 |
}
|
53 |
|
54 |
$this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var'));
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Error\SyntaxError;
|
13 |
+
use Twig\Node\Expression\AssignNameExpression;
|
14 |
+
use Twig\Node\ImportNode;
|
15 |
+
use Twig\Token;
|
16 |
+
use Twig\TokenParser\AbstractTokenParser;
|
17 |
+
|
18 |
/**
|
19 |
* Imports macros.
|
20 |
*
|
|
|
21 |
* {% from 'forms.html' import forms %}
|
|
|
22 |
*
|
23 |
* @final
|
24 |
*/
|
25 |
+
class Twig_TokenParser_From extends AbstractTokenParser
|
26 |
{
|
27 |
+
public function parse(Token $token)
|
28 |
{
|
29 |
$macro = $this->parser->getExpressionParser()->parseExpression();
|
30 |
$stream = $this->parser->getStream();
|
32 |
|
33 |
$targets = [];
|
34 |
do {
|
35 |
+
$name = $stream->expect(Token::NAME_TYPE)->getValue();
|
36 |
|
37 |
$alias = $name;
|
38 |
if ($stream->nextIf('as')) {
|
39 |
+
$alias = $stream->expect(Token::NAME_TYPE)->getValue();
|
40 |
}
|
41 |
|
42 |
$targets[$name] = $alias;
|
43 |
|
44 |
+
if (!$stream->nextIf(Token::PUNCTUATION_TYPE, ',')) {
|
45 |
break;
|
46 |
}
|
47 |
} while (true);
|
48 |
|
49 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
50 |
|
51 |
+
$node = new ImportNode($macro, new AssignNameExpression($this->parser->getVarName(), $token->getLine()), $token->getLine(), $this->getTag());
|
52 |
|
53 |
foreach ($targets as $name => $alias) {
|
54 |
if ($this->parser->isReservedMacroName($name)) {
|
55 |
+
throw new SyntaxError(sprintf('"%s" cannot be an imported macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext());
|
56 |
}
|
57 |
|
58 |
$this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var'));
|
vendor/twig/twig/lib/Twig/TokenParser/If.php
CHANGED
@@ -10,29 +10,33 @@
|
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
/**
|
14 |
* Tests a condition.
|
15 |
*
|
16 |
-
*
|
17 |
-
*
|
18 |
-
*
|
19 |
-
*
|
20 |
-
*
|
21 |
-
*
|
22 |
-
*
|
23 |
-
* {% endif %}
|
24 |
-
* </pre>
|
25 |
*
|
26 |
* @final
|
27 |
*/
|
28 |
-
class Twig_TokenParser_If extends
|
29 |
{
|
30 |
-
public function parse(
|
31 |
{
|
32 |
$lineno = $token->getLine();
|
33 |
$expr = $this->parser->getExpressionParser()->parseExpression();
|
34 |
$stream = $this->parser->getStream();
|
35 |
-
$stream->expect(
|
36 |
$body = $this->parser->subparse([$this, 'decideIfFork']);
|
37 |
$tests = [$expr, $body];
|
38 |
$else = null;
|
@@ -41,13 +45,13 @@ class Twig_TokenParser_If extends Twig_TokenParser
|
|
41 |
while (!$end) {
|
42 |
switch ($stream->next()->getValue()) {
|
43 |
case 'else':
|
44 |
-
$stream->expect(
|
45 |
$else = $this->parser->subparse([$this, 'decideIfEnd']);
|
46 |
break;
|
47 |
|
48 |
case 'elseif':
|
49 |
$expr = $this->parser->getExpressionParser()->parseExpression();
|
50 |
-
$stream->expect(
|
51 |
$body = $this->parser->subparse([$this, 'decideIfFork']);
|
52 |
$tests[] = $expr;
|
53 |
$tests[] = $body;
|
@@ -58,21 +62,21 @@ class Twig_TokenParser_If extends Twig_TokenParser
|
|
58 |
break;
|
59 |
|
60 |
default:
|
61 |
-
throw new
|
62 |
}
|
63 |
}
|
64 |
|
65 |
-
$stream->expect(
|
66 |
|
67 |
-
return new
|
68 |
}
|
69 |
|
70 |
-
public function decideIfFork(
|
71 |
{
|
72 |
return $token->test(['elseif', 'else', 'endif']);
|
73 |
}
|
74 |
|
75 |
-
public function decideIfEnd(
|
76 |
{
|
77 |
return $token->test(['endif']);
|
78 |
}
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Error\SyntaxError;
|
14 |
+
use Twig\Node\IfNode;
|
15 |
+
use Twig\Node\Node;
|
16 |
+
use Twig\Token;
|
17 |
+
use Twig\TokenParser\AbstractTokenParser;
|
18 |
+
|
19 |
/**
|
20 |
* Tests a condition.
|
21 |
*
|
22 |
+
* {% if users %}
|
23 |
+
* <ul>
|
24 |
+
* {% for user in users %}
|
25 |
+
* <li>{{ user.username|e }}</li>
|
26 |
+
* {% endfor %}
|
27 |
+
* </ul>
|
28 |
+
* {% endif %}
|
|
|
|
|
29 |
*
|
30 |
* @final
|
31 |
*/
|
32 |
+
class Twig_TokenParser_If extends AbstractTokenParser
|
33 |
{
|
34 |
+
public function parse(Token $token)
|
35 |
{
|
36 |
$lineno = $token->getLine();
|
37 |
$expr = $this->parser->getExpressionParser()->parseExpression();
|
38 |
$stream = $this->parser->getStream();
|
39 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
40 |
$body = $this->parser->subparse([$this, 'decideIfFork']);
|
41 |
$tests = [$expr, $body];
|
42 |
$else = null;
|
45 |
while (!$end) {
|
46 |
switch ($stream->next()->getValue()) {
|
47 |
case 'else':
|
48 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
49 |
$else = $this->parser->subparse([$this, 'decideIfEnd']);
|
50 |
break;
|
51 |
|
52 |
case 'elseif':
|
53 |
$expr = $this->parser->getExpressionParser()->parseExpression();
|
54 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
55 |
$body = $this->parser->subparse([$this, 'decideIfFork']);
|
56 |
$tests[] = $expr;
|
57 |
$tests[] = $body;
|
62 |
break;
|
63 |
|
64 |
default:
|
65 |
+
throw new SyntaxError(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());
|
66 |
}
|
67 |
}
|
68 |
|
69 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
70 |
|
71 |
+
return new IfNode(new Node($tests), $else, $lineno, $this->getTag());
|
72 |
}
|
73 |
|
74 |
+
public function decideIfFork(Token $token)
|
75 |
{
|
76 |
return $token->test(['elseif', 'else', 'endif']);
|
77 |
}
|
78 |
|
79 |
+
public function decideIfEnd(Token $token)
|
80 |
{
|
81 |
return $token->test(['endif']);
|
82 |
}
|
vendor/twig/twig/lib/Twig/TokenParser/Import.php
CHANGED
@@ -9,27 +9,30 @@
|
|
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
|
22 |
{
|
23 |
-
public function parse(
|
24 |
{
|
25 |
$macro = $this->parser->getExpressionParser()->parseExpression();
|
26 |
$this->parser->getStream()->expect('as');
|
27 |
-
$var = new
|
28 |
-
$this->parser->getStream()->expect(
|
29 |
|
30 |
$this->parser->addImportedSymbol('template', $var->getAttribute('name'));
|
31 |
|
32 |
-
return new
|
33 |
}
|
34 |
|
35 |
public function getTag()
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Node\Expression\AssignNameExpression;
|
13 |
+
use Twig\Node\ImportNode;
|
14 |
+
use Twig\Token;
|
15 |
+
use Twig\TokenParser\AbstractTokenParser;
|
16 |
+
|
17 |
/**
|
18 |
* Imports macros.
|
19 |
*
|
|
|
20 |
* {% import 'forms.html' as forms %}
|
|
|
21 |
*
|
22 |
* @final
|
23 |
*/
|
24 |
+
class Twig_TokenParser_Import extends AbstractTokenParser
|
25 |
{
|
26 |
+
public function parse(Token $token)
|
27 |
{
|
28 |
$macro = $this->parser->getExpressionParser()->parseExpression();
|
29 |
$this->parser->getStream()->expect('as');
|
30 |
+
$var = new AssignNameExpression($this->parser->getStream()->expect(Token::NAME_TYPE)->getValue(), $token->getLine());
|
31 |
+
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
32 |
|
33 |
$this->parser->addImportedSymbol('template', $var->getAttribute('name'));
|
34 |
|
35 |
+
return new ImportNode($macro, $var, $token->getLine(), $this->getTag());
|
36 |
}
|
37 |
|
38 |
public function getTag()
|
vendor/twig/twig/lib/Twig/TokenParser/Include.php
CHANGED
@@ -10,24 +10,26 @@
|
|
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
|
23 |
{
|
24 |
-
public function parse(
|
25 |
{
|
26 |
$expr = $this->parser->getExpressionParser()->parseExpression();
|
27 |
|
28 |
list($variables, $only, $ignoreMissing) = $this->parseArguments();
|
29 |
|
30 |
-
return new
|
31 |
}
|
32 |
|
33 |
protected function parseArguments()
|
@@ -35,23 +37,23 @@ class Twig_TokenParser_Include extends Twig_TokenParser
|
|
35 |
$stream = $this->parser->getStream();
|
36 |
|
37 |
$ignoreMissing = false;
|
38 |
-
if ($stream->nextIf(
|
39 |
-
$stream->expect(
|
40 |
|
41 |
$ignoreMissing = true;
|
42 |
}
|
43 |
|
44 |
$variables = null;
|
45 |
-
if ($stream->nextIf(
|
46 |
$variables = $this->parser->getExpressionParser()->parseExpression();
|
47 |
}
|
48 |
|
49 |
$only = false;
|
50 |
-
if ($stream->nextIf(
|
51 |
$only = true;
|
52 |
}
|
53 |
|
54 |
-
$stream->expect(
|
55 |
|
56 |
return [$variables, $only, $ignoreMissing];
|
57 |
}
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Node\IncludeNode;
|
14 |
+
use Twig\Token;
|
15 |
+
use Twig\TokenParser\AbstractTokenParser;
|
16 |
+
|
17 |
/**
|
18 |
* Includes a template.
|
19 |
*
|
|
|
20 |
* {% include 'header.html' %}
|
21 |
* Body
|
22 |
* {% include 'footer.html' %}
|
|
|
23 |
*/
|
24 |
+
class Twig_TokenParser_Include extends AbstractTokenParser
|
25 |
{
|
26 |
+
public function parse(Token $token)
|
27 |
{
|
28 |
$expr = $this->parser->getExpressionParser()->parseExpression();
|
29 |
|
30 |
list($variables, $only, $ignoreMissing) = $this->parseArguments();
|
31 |
|
32 |
+
return new IncludeNode($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag());
|
33 |
}
|
34 |
|
35 |
protected function parseArguments()
|
37 |
$stream = $this->parser->getStream();
|
38 |
|
39 |
$ignoreMissing = false;
|
40 |
+
if ($stream->nextIf(Token::NAME_TYPE, 'ignore')) {
|
41 |
+
$stream->expect(Token::NAME_TYPE, 'missing');
|
42 |
|
43 |
$ignoreMissing = true;
|
44 |
}
|
45 |
|
46 |
$variables = null;
|
47 |
+
if ($stream->nextIf(Token::NAME_TYPE, 'with')) {
|
48 |
$variables = $this->parser->getExpressionParser()->parseExpression();
|
49 |
}
|
50 |
|
51 |
$only = false;
|
52 |
+
if ($stream->nextIf(Token::NAME_TYPE, 'only')) {
|
53 |
$only = true;
|
54 |
}
|
55 |
|
56 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
57 |
|
58 |
return [$variables, $only, $ignoreMissing];
|
59 |
}
|
vendor/twig/twig/lib/Twig/TokenParser/Macro.php
CHANGED
@@ -9,44 +9,48 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Defines a macro.
|
14 |
*
|
15 |
-
*
|
16 |
-
* {
|
17 |
-
*
|
18 |
-
* {% endmacro %}
|
19 |
-
* </pre>
|
20 |
*
|
21 |
* @final
|
22 |
*/
|
23 |
-
class Twig_TokenParser_Macro extends
|
24 |
{
|
25 |
-
public function parse(
|
26 |
{
|
27 |
$lineno = $token->getLine();
|
28 |
$stream = $this->parser->getStream();
|
29 |
-
$name = $stream->expect(
|
30 |
|
31 |
$arguments = $this->parser->getExpressionParser()->parseArguments(true, true);
|
32 |
|
33 |
-
$stream->expect(
|
34 |
$this->parser->pushLocalScope();
|
35 |
$body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
|
36 |
-
if ($token = $stream->nextIf(
|
37 |
$value = $token->getValue();
|
38 |
|
39 |
if ($value != $name) {
|
40 |
-
throw new
|
41 |
}
|
42 |
}
|
43 |
$this->parser->popLocalScope();
|
44 |
-
$stream->expect(
|
45 |
|
46 |
-
$this->parser->setMacro($name, new
|
47 |
}
|
48 |
|
49 |
-
public function decideBlockEnd(
|
50 |
{
|
51 |
return $token->test('endmacro');
|
52 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Error\SyntaxError;
|
13 |
+
use Twig\Node\BodyNode;
|
14 |
+
use Twig\Node\MacroNode;
|
15 |
+
use Twig\Token;
|
16 |
+
use Twig\TokenParser\AbstractTokenParser;
|
17 |
+
|
18 |
/**
|
19 |
* Defines a macro.
|
20 |
*
|
21 |
+
* {% macro input(name, value, type, size) %}
|
22 |
+
* <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
|
23 |
+
* {% endmacro %}
|
|
|
|
|
24 |
*
|
25 |
* @final
|
26 |
*/
|
27 |
+
class Twig_TokenParser_Macro extends AbstractTokenParser
|
28 |
{
|
29 |
+
public function parse(Token $token)
|
30 |
{
|
31 |
$lineno = $token->getLine();
|
32 |
$stream = $this->parser->getStream();
|
33 |
+
$name = $stream->expect(Token::NAME_TYPE)->getValue();
|
34 |
|
35 |
$arguments = $this->parser->getExpressionParser()->parseArguments(true, true);
|
36 |
|
37 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
38 |
$this->parser->pushLocalScope();
|
39 |
$body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
|
40 |
+
if ($token = $stream->nextIf(Token::NAME_TYPE)) {
|
41 |
$value = $token->getValue();
|
42 |
|
43 |
if ($value != $name) {
|
44 |
+
throw new SyntaxError(sprintf('Expected endmacro for macro "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext());
|
45 |
}
|
46 |
}
|
47 |
$this->parser->popLocalScope();
|
48 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
49 |
|
50 |
+
$this->parser->setMacro($name, new MacroNode($name, new BodyNode([$body]), $arguments, $lineno, $this->getTag()));
|
51 |
}
|
52 |
|
53 |
+
public function decideBlockEnd(Token $token)
|
54 |
{
|
55 |
return $token->test('endmacro');
|
56 |
}
|
vendor/twig/twig/lib/Twig/TokenParser/Sandbox.php
CHANGED
@@ -9,45 +9,50 @@
|
|
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 |
-
*
|
16 |
-
*
|
17 |
-
*
|
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
|
26 |
{
|
27 |
-
public function parse(
|
28 |
{
|
29 |
$stream = $this->parser->getStream();
|
30 |
-
$stream->expect(
|
31 |
$body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
|
32 |
-
$stream->expect(
|
33 |
|
34 |
// in a sandbox tag, only include tags are allowed
|
35 |
-
if (!$body instanceof
|
36 |
foreach ($body as $node) {
|
37 |
-
if ($node instanceof
|
38 |
continue;
|
39 |
}
|
40 |
|
41 |
-
if (!$node instanceof
|
42 |
-
throw new
|
43 |
}
|
44 |
}
|
45 |
}
|
46 |
|
47 |
-
return new
|
48 |
}
|
49 |
|
50 |
-
public function decideBlockEnd(
|
51 |
{
|
52 |
return $token->test('endsandbox');
|
53 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Error\SyntaxError;
|
13 |
+
use Twig\Node\IncludeNode;
|
14 |
+
use Twig\Node\SandboxNode;
|
15 |
+
use Twig\Node\TextNode;
|
16 |
+
use Twig\Token;
|
17 |
+
use Twig\TokenParser\AbstractTokenParser;
|
18 |
+
|
19 |
/**
|
20 |
* Marks a section of a template as untrusted code that must be evaluated in the sandbox mode.
|
21 |
*
|
22 |
+
* {% sandbox %}
|
23 |
+
* {% include 'user.html' %}
|
24 |
+
* {% endsandbox %}
|
|
|
|
|
25 |
*
|
26 |
* @see https://twig.symfony.com/doc/api.html#sandbox-extension for details
|
27 |
*
|
28 |
* @final
|
29 |
*/
|
30 |
+
class Twig_TokenParser_Sandbox extends AbstractTokenParser
|
31 |
{
|
32 |
+
public function parse(Token $token)
|
33 |
{
|
34 |
$stream = $this->parser->getStream();
|
35 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
36 |
$body = $this->parser->subparse([$this, 'decideBlockEnd'], true);
|
37 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
38 |
|
39 |
// in a sandbox tag, only include tags are allowed
|
40 |
+
if (!$body instanceof IncludeNode) {
|
41 |
foreach ($body as $node) {
|
42 |
+
if ($node instanceof TextNode && ctype_space($node->getAttribute('data'))) {
|
43 |
continue;
|
44 |
}
|
45 |
|
46 |
+
if (!$node instanceof IncludeNode) {
|
47 |
+
throw new SyntaxError('Only "include" tags are allowed within a "sandbox" section.', $node->getTemplateLine(), $stream->getSourceContext());
|
48 |
}
|
49 |
}
|
50 |
}
|
51 |
|
52 |
+
return new SandboxNode($body, $token->getLine(), $this->getTag());
|
53 |
}
|
54 |
|
55 |
+
public function decideBlockEnd(Token $token)
|
56 |
{
|
57 |
return $token->test('endsandbox');
|
58 |
}
|
vendor/twig/twig/lib/Twig/TokenParser/Set.php
CHANGED
@@ -9,59 +9,57 @@
|
|
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
|
32 |
{
|
33 |
-
public function parse(
|
34 |
{
|
35 |
$lineno = $token->getLine();
|
36 |
$stream = $this->parser->getStream();
|
37 |
$names = $this->parser->getExpressionParser()->parseAssignmentExpression();
|
38 |
|
39 |
$capture = false;
|
40 |
-
if ($stream->nextIf(
|
41 |
$values = $this->parser->getExpressionParser()->parseMultitargetExpression();
|
42 |
|
43 |
-
$stream->expect(
|
44 |
|
45 |
-
if (count($names) !== count($values)) {
|
46 |
-
throw new
|
47 |
}
|
48 |
} else {
|
49 |
$capture = true;
|
50 |
|
51 |
-
if (count($names) > 1) {
|
52 |
-
throw new
|
53 |
}
|
54 |
|
55 |
-
$stream->expect(
|
56 |
|
57 |
$values = $this->parser->subparse([$this, 'decideBlockEnd'], true);
|
58 |
-
$stream->expect(
|
59 |
}
|
60 |
|
61 |
-
return new
|
62 |
}
|
63 |
|
64 |
-
public function decideBlockEnd(
|
65 |
{
|
66 |
return $token->test('endset');
|
67 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Error\SyntaxError;
|
13 |
+
use Twig\Node\SetNode;
|
14 |
+
use Twig\Token;
|
15 |
+
use Twig\TokenParser\AbstractTokenParser;
|
16 |
+
|
17 |
/**
|
18 |
* Defines a variable.
|
19 |
*
|
|
|
20 |
* {% set foo = 'foo' %}
|
|
|
21 |
* {% set foo = [1, 2] %}
|
|
|
22 |
* {% set foo = {'foo': 'bar'} %}
|
|
|
23 |
* {% set foo = 'foo' ~ 'bar' %}
|
|
|
24 |
* {% set foo, bar = 'foo', 'bar' %}
|
|
|
25 |
* {% set foo %}Some content{% endset %}
|
|
|
26 |
*
|
27 |
* @final
|
28 |
*/
|
29 |
+
class Twig_TokenParser_Set extends AbstractTokenParser
|
30 |
{
|
31 |
+
public function parse(Token $token)
|
32 |
{
|
33 |
$lineno = $token->getLine();
|
34 |
$stream = $this->parser->getStream();
|
35 |
$names = $this->parser->getExpressionParser()->parseAssignmentExpression();
|
36 |
|
37 |
$capture = false;
|
38 |
+
if ($stream->nextIf(Token::OPERATOR_TYPE, '=')) {
|
39 |
$values = $this->parser->getExpressionParser()->parseMultitargetExpression();
|
40 |
|
41 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
42 |
|
43 |
+
if (\count($names) !== \count($values)) {
|
44 |
+
throw new SyntaxError('When using set, you must have the same number of variables and assignments.', $stream->getCurrent()->getLine(), $stream->getSourceContext());
|
45 |
}
|
46 |
} else {
|
47 |
$capture = true;
|
48 |
|
49 |
+
if (\count($names) > 1) {
|
50 |
+
throw new SyntaxError('When using set with a block, you cannot have a multi-target.', $stream->getCurrent()->getLine(), $stream->getSourceContext());
|
51 |
}
|
52 |
|
53 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
54 |
|
55 |
$values = $this->parser->subparse([$this, 'decideBlockEnd'], true);
|
56 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
57 |
}
|
58 |
|
59 |
+
return new SetNode($capture, $names, $values, $lineno, $this->getTag());
|
60 |
}
|
61 |
|
62 |
+
public function decideBlockEnd(Token $token)
|
63 |
{
|
64 |
return $token->test('endset');
|
65 |
}
|
vendor/twig/twig/lib/Twig/TokenParser/Spaceless.php
CHANGED
@@ -9,35 +9,36 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Remove whitespaces between HTML tags.
|
14 |
*
|
15 |
-
*
|
16 |
-
* {% spaceless %}
|
17 |
* <div>
|
18 |
* <strong>foo</strong>
|
19 |
* </div>
|
20 |
-
*
|
21 |
-
*
|
22 |
-
* {# output will be <div><strong>foo</strong></div> #}
|
23 |
-
* </pre>
|
24 |
*
|
25 |
* @final
|
26 |
*/
|
27 |
-
class Twig_TokenParser_Spaceless extends
|
28 |
{
|
29 |
-
public function parse(
|
30 |
{
|
31 |
$lineno = $token->getLine();
|
32 |
|
33 |
-
$this->parser->getStream()->expect(
|
34 |
$body = $this->parser->subparse([$this, 'decideSpacelessEnd'], true);
|
35 |
-
$this->parser->getStream()->expect(
|
36 |
|
37 |
-
return new
|
38 |
}
|
39 |
|
40 |
-
public function decideSpacelessEnd(
|
41 |
{
|
42 |
return $token->test('endspaceless');
|
43 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Node\SpacelessNode;
|
13 |
+
use Twig\Token;
|
14 |
+
use Twig\TokenParser\AbstractTokenParser;
|
15 |
+
|
16 |
/**
|
17 |
* Remove whitespaces between HTML tags.
|
18 |
*
|
19 |
+
* {% spaceless %}
|
|
|
20 |
* <div>
|
21 |
* <strong>foo</strong>
|
22 |
* </div>
|
23 |
+
* {% endspaceless %}
|
24 |
+
* {# output will be <div><strong>foo</strong></div> #}
|
|
|
|
|
25 |
*
|
26 |
* @final
|
27 |
*/
|
28 |
+
class Twig_TokenParser_Spaceless extends AbstractTokenParser
|
29 |
{
|
30 |
+
public function parse(Token $token)
|
31 |
{
|
32 |
$lineno = $token->getLine();
|
33 |
|
34 |
+
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
35 |
$body = $this->parser->subparse([$this, 'decideSpacelessEnd'], true);
|
36 |
+
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
37 |
|
38 |
+
return new SpacelessNode($body, $lineno, $this->getTag());
|
39 |
}
|
40 |
|
41 |
+
public function decideSpacelessEnd(Token $token)
|
42 |
{
|
43 |
return $token->test('endspaceless');
|
44 |
}
|
vendor/twig/twig/lib/Twig/TokenParser/Use.php
CHANGED
@@ -9,56 +9,60 @@
|
|
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 |
-
*
|
16 |
-
* {% extends "base.html" %}
|
17 |
*
|
18 |
-
*
|
19 |
*
|
20 |
-
*
|
21 |
-
*
|
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
|
29 |
{
|
30 |
-
public function parse(
|
31 |
{
|
32 |
$template = $this->parser->getExpressionParser()->parseExpression();
|
33 |
$stream = $this->parser->getStream();
|
34 |
|
35 |
-
if (!$template instanceof
|
36 |
-
throw new
|
37 |
}
|
38 |
|
39 |
$targets = [];
|
40 |
if ($stream->nextIf('with')) {
|
41 |
do {
|
42 |
-
$name = $stream->expect(
|
43 |
|
44 |
$alias = $name;
|
45 |
if ($stream->nextIf('as')) {
|
46 |
-
$alias = $stream->expect(
|
47 |
}
|
48 |
|
49 |
-
$targets[$name] = new
|
50 |
|
51 |
-
if (!$stream->nextIf(
|
52 |
break;
|
53 |
}
|
54 |
} while (true);
|
55 |
}
|
56 |
|
57 |
-
$stream->expect(
|
58 |
|
59 |
-
$this->parser->addTrait(new
|
60 |
|
61 |
-
return new
|
62 |
}
|
63 |
|
64 |
public function getTag()
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Error\SyntaxError;
|
13 |
+
use Twig\Node\Expression\ConstantExpression;
|
14 |
+
use Twig\Node\Node;
|
15 |
+
use Twig\Token;
|
16 |
+
use Twig\TokenParser\AbstractTokenParser;
|
17 |
+
|
18 |
/**
|
19 |
* Imports blocks defined in another template into the current template.
|
20 |
*
|
21 |
+
* {% extends "base.html" %}
|
|
|
22 |
*
|
23 |
+
* {% use "blocks.html" %}
|
24 |
*
|
25 |
+
* {% block title %}{% endblock %}
|
26 |
+
* {% block content %}{% endblock %}
|
|
|
27 |
*
|
28 |
* @see https://twig.symfony.com/doc/templates.html#horizontal-reuse for details.
|
29 |
*
|
30 |
* @final
|
31 |
*/
|
32 |
+
class Twig_TokenParser_Use extends AbstractTokenParser
|
33 |
{
|
34 |
+
public function parse(Token $token)
|
35 |
{
|
36 |
$template = $this->parser->getExpressionParser()->parseExpression();
|
37 |
$stream = $this->parser->getStream();
|
38 |
|
39 |
+
if (!$template instanceof ConstantExpression) {
|
40 |
+
throw new SyntaxError('The template references in a "use" statement must be a string.', $stream->getCurrent()->getLine(), $stream->getSourceContext());
|
41 |
}
|
42 |
|
43 |
$targets = [];
|
44 |
if ($stream->nextIf('with')) {
|
45 |
do {
|
46 |
+
$name = $stream->expect(Token::NAME_TYPE)->getValue();
|
47 |
|
48 |
$alias = $name;
|
49 |
if ($stream->nextIf('as')) {
|
50 |
+
$alias = $stream->expect(Token::NAME_TYPE)->getValue();
|
51 |
}
|
52 |
|
53 |
+
$targets[$name] = new ConstantExpression($alias, -1);
|
54 |
|
55 |
+
if (!$stream->nextIf(Token::PUNCTUATION_TYPE, ',')) {
|
56 |
break;
|
57 |
}
|
58 |
} while (true);
|
59 |
}
|
60 |
|
61 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
62 |
|
63 |
+
$this->parser->addTrait(new Node(['template' => $template, 'targets' => new Node($targets)]));
|
64 |
|
65 |
+
return new Node();
|
66 |
}
|
67 |
|
68 |
public function getTag()
|
vendor/twig/twig/lib/Twig/TokenParser/With.php
CHANGED
@@ -9,6 +9,10 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Creates a nested scope.
|
14 |
*
|
@@ -16,29 +20,29 @@
|
|
16 |
*
|
17 |
* @final
|
18 |
*/
|
19 |
-
class Twig_TokenParser_With extends
|
20 |
{
|
21 |
-
public function parse(
|
22 |
{
|
23 |
$stream = $this->parser->getStream();
|
24 |
|
25 |
$variables = null;
|
26 |
$only = false;
|
27 |
-
if (!$stream->test(
|
28 |
$variables = $this->parser->getExpressionParser()->parseExpression();
|
29 |
-
$only = $stream->nextIf(
|
30 |
}
|
31 |
|
32 |
-
$stream->expect(
|
33 |
|
34 |
$body = $this->parser->subparse([$this, 'decideWithEnd'], true);
|
35 |
|
36 |
-
$stream->expect(
|
37 |
|
38 |
-
return new
|
39 |
}
|
40 |
|
41 |
-
public function decideWithEnd(
|
42 |
{
|
43 |
return $token->test('endwith');
|
44 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Node\WithNode;
|
13 |
+
use Twig\Token;
|
14 |
+
use Twig\TokenParser\AbstractTokenParser;
|
15 |
+
|
16 |
/**
|
17 |
* Creates a nested scope.
|
18 |
*
|
20 |
*
|
21 |
* @final
|
22 |
*/
|
23 |
+
class Twig_TokenParser_With extends AbstractTokenParser
|
24 |
{
|
25 |
+
public function parse(Token $token)
|
26 |
{
|
27 |
$stream = $this->parser->getStream();
|
28 |
|
29 |
$variables = null;
|
30 |
$only = false;
|
31 |
+
if (!$stream->test(Token::BLOCK_END_TYPE)) {
|
32 |
$variables = $this->parser->getExpressionParser()->parseExpression();
|
33 |
+
$only = $stream->nextIf(Token::NAME_TYPE, 'only');
|
34 |
}
|
35 |
|
36 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
37 |
|
38 |
$body = $this->parser->subparse([$this, 'decideWithEnd'], true);
|
39 |
|
40 |
+
$stream->expect(Token::BLOCK_END_TYPE);
|
41 |
|
42 |
+
return new WithNode($body, $variables, $only, $token->getLine(), $this->getTag());
|
43 |
}
|
44 |
|
45 |
+
public function decideWithEnd(Token $token)
|
46 |
{
|
47 |
return $token->test('endwith');
|
48 |
}
|
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
|
28 |
-
* @param array
|
29 |
-
* @param bool
|
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
|
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(
|
52 |
{
|
53 |
$this->parsers[$parser->getTag()] = $parser;
|
54 |
}
|
55 |
|
56 |
-
public function removeTokenParser(
|
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
|
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 |
{
|
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
|
30 |
*/
|
31 |
public function getTokenParser($tag);
|
32 |
|
33 |
/**
|
34 |
-
* Calls
|
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 |
|
vendor/twig/twig/lib/Twig/TokenParserInterface.php
CHANGED
@@ -9,6 +9,10 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* Interface implemented by token parsers.
|
14 |
*
|
@@ -19,16 +23,16 @@ interface Twig_TokenParserInterface
|
|
19 |
/**
|
20 |
* Sets the parser associated with this token parser.
|
21 |
*/
|
22 |
-
public function setParser(
|
23 |
|
24 |
/**
|
25 |
* Parses a token and returns a node.
|
26 |
*
|
27 |
* @return Twig_NodeInterface
|
28 |
*
|
29 |
-
* @throws
|
30 |
*/
|
31 |
-
public function parse(
|
32 |
|
33 |
/**
|
34 |
* Gets the tag name associated with this token parser.
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Error\SyntaxError;
|
13 |
+
use Twig\Parser;
|
14 |
+
use Twig\Token;
|
15 |
+
|
16 |
/**
|
17 |
* Interface implemented by token parsers.
|
18 |
*
|
23 |
/**
|
24 |
* Sets the parser associated with this token parser.
|
25 |
*/
|
26 |
+
public function setParser(Parser $parser);
|
27 |
|
28 |
/**
|
29 |
* Parses a token and returns a node.
|
30 |
*
|
31 |
* @return Twig_NodeInterface
|
32 |
*
|
33 |
+
* @throws SyntaxError
|
34 |
*/
|
35 |
+
public function parse(Token $token);
|
36 |
|
37 |
/**
|
38 |
* Gets the tag name associated with this token parser.
|
vendor/twig/twig/lib/Twig/TokenStream.php
CHANGED
@@ -10,6 +10,10 @@
|
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
|
|
|
|
|
|
|
|
13 |
/**
|
14 |
* Represents a token stream.
|
15 |
*
|
@@ -32,11 +36,11 @@ class Twig_TokenStream
|
|
32 |
*/
|
33 |
public function __construct(array $tokens, $name = null, $source = null)
|
34 |
{
|
35 |
-
if (!$name instanceof
|
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
|
40 |
} else {
|
41 |
$this->source = $name;
|
42 |
}
|
@@ -54,18 +58,18 @@ class Twig_TokenStream
|
|
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
|
64 |
*/
|
65 |
public function next()
|
66 |
{
|
67 |
if (!isset($this->tokens[++$this->current])) {
|
68 |
-
throw new
|
69 |
}
|
70 |
|
71 |
return $this->tokens[$this->current - 1];
|
@@ -74,7 +78,7 @@ class Twig_TokenStream
|
|
74 |
/**
|
75 |
* Tests a token, sets the pointer to the next one and returns it or throws a syntax error.
|
76 |
*
|
77 |
-
* @return
|
78 |
*/
|
79 |
public function nextIf($primary, $secondary = null)
|
80 |
{
|
@@ -86,17 +90,17 @@ class Twig_TokenStream
|
|
86 |
/**
|
87 |
* Tests a token and returns it or throws a syntax error.
|
88 |
*
|
89 |
-
* @return
|
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
|
97 |
$message ? $message.'. ' : '',
|
98 |
-
|
99 |
-
|
100 |
$line,
|
101 |
$this->source
|
102 |
);
|
@@ -111,12 +115,12 @@ class Twig_TokenStream
|
|
111 |
*
|
112 |
* @param int $number
|
113 |
*
|
114 |
-
* @return
|
115 |
*/
|
116 |
public function look($number = 1)
|
117 |
{
|
118 |
if (!isset($this->tokens[$this->current + $number])) {
|
119 |
-
throw new
|
120 |
}
|
121 |
|
122 |
return $this->tokens[$this->current + $number];
|
@@ -139,11 +143,11 @@ class Twig_TokenStream
|
|
139 |
*/
|
140 |
public function isEOF()
|
141 |
{
|
142 |
-
return
|
143 |
}
|
144 |
|
145 |
/**
|
146 |
-
* @return
|
147 |
*/
|
148 |
public function getCurrent()
|
149 |
{
|
@@ -183,7 +187,7 @@ class Twig_TokenStream
|
|
183 |
/**
|
184 |
* Gets the source associated with this stream.
|
185 |
*
|
186 |
-
* @return
|
187 |
*
|
188 |
* @internal
|
189 |
*/
|
10 |
* file that was distributed with this source code.
|
11 |
*/
|
12 |
|
13 |
+
use Twig\Error\SyntaxError;
|
14 |
+
use Twig\Source;
|
15 |
+
use Twig\Token;
|
16 |
+
|
17 |
/**
|
18 |
* Represents a token stream.
|
19 |
*
|
36 |
*/
|
37 |
public function __construct(array $tokens, $name = null, $source = null)
|
38 |
{
|
39 |
+
if (!$name instanceof Source) {
|
40 |
if (null !== $name || null !== $source) {
|
41 |
@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);
|
42 |
}
|
43 |
+
$this->source = new Source($source, $name);
|
44 |
} else {
|
45 |
$this->source = $name;
|
46 |
}
|
58 |
|
59 |
public function injectTokens(array $tokens)
|
60 |
{
|
61 |
+
$this->tokens = array_merge(\array_slice($this->tokens, 0, $this->current), $tokens, \array_slice($this->tokens, $this->current));
|
62 |
}
|
63 |
|
64 |
/**
|
65 |
* Sets the pointer to the next token and returns the old one.
|
66 |
*
|
67 |
+
* @return Token
|
68 |
*/
|
69 |
public function next()
|
70 |
{
|
71 |
if (!isset($this->tokens[++$this->current])) {
|
72 |
+
throw new SyntaxError('Unexpected end of template.', $this->tokens[$this->current - 1]->getLine(), $this->source);
|
73 |
}
|
74 |
|
75 |
return $this->tokens[$this->current - 1];
|
78 |
/**
|
79 |
* Tests a token, sets the pointer to the next one and returns it or throws a syntax error.
|
80 |
*
|
81 |
+
* @return Token|null The next token if the condition is true, null otherwise
|
82 |
*/
|
83 |
public function nextIf($primary, $secondary = null)
|
84 |
{
|
90 |
/**
|
91 |
* Tests a token and returns it or throws a syntax error.
|
92 |
*
|
93 |
+
* @return Token
|
94 |
*/
|
95 |
public function expect($type, $value = null, $message = null)
|
96 |
{
|
97 |
$token = $this->tokens[$this->current];
|
98 |
if (!$token->test($type, $value)) {
|
99 |
$line = $token->getLine();
|
100 |
+
throw new SyntaxError(sprintf('%sUnexpected token "%s" of value "%s" ("%s" expected%s).',
|
101 |
$message ? $message.'. ' : '',
|
102 |
+
Token::typeToEnglish($token->getType()), $token->getValue(),
|
103 |
+
Token::typeToEnglish($type), $value ? sprintf(' with value "%s"', $value) : ''),
|
104 |
$line,
|
105 |
$this->source
|
106 |
);
|
115 |
*
|
116 |
* @param int $number
|
117 |
*
|
118 |
+
* @return Token
|
119 |
*/
|
120 |
public function look($number = 1)
|
121 |
{
|
122 |
if (!isset($this->tokens[$this->current + $number])) {
|
123 |
+
throw new SyntaxError('Unexpected end of template.', $this->tokens[$this->current + $number - 1]->getLine(), $this->source);
|
124 |
}
|
125 |
|
126 |
return $this->tokens[$this->current + $number];
|
143 |
*/
|
144 |
public function isEOF()
|
145 |
{
|
146 |
+
return Token::EOF_TYPE === $this->tokens[$this->current]->getType();
|
147 |
}
|
148 |
|
149 |
/**
|
150 |
+
* @return Token
|
151 |
*/
|
152 |
public function getCurrent()
|
153 |
{
|
187 |
/**
|
188 |
* Gets the source associated with this stream.
|
189 |
*
|
190 |
+
* @return Source
|
191 |
*
|
192 |
* @internal
|
193 |
*/
|
vendor/twig/twig/lib/Twig/Util/DeprecationCollector.php
CHANGED
@@ -9,6 +9,11 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
|
|
12 |
/**
|
13 |
* @author Fabien Potencier <fabien@symfony.com>
|
14 |
*
|
@@ -19,7 +24,7 @@ class Twig_Util_DeprecationCollector
|
|
19 |
private $twig;
|
20 |
private $deprecations;
|
21 |
|
22 |
-
public function __construct(
|
23 |
{
|
24 |
$this->twig = $twig;
|
25 |
}
|
@@ -34,23 +39,23 @@ class Twig_Util_DeprecationCollector
|
|
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
|
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 |
|
@@ -58,8 +63,8 @@ class Twig_Util_DeprecationCollector
|
|
58 |
|
59 |
foreach ($iterator as $name => $contents) {
|
60 |
try {
|
61 |
-
$this->twig->parse($this->twig->tokenize(new
|
62 |
-
} catch (
|
63 |
// ignore templates containing syntax errors
|
64 |
}
|
65 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Environment;
|
13 |
+
use Twig\Error\SyntaxError;
|
14 |
+
use Twig\Source;
|
15 |
+
use Twig\Util\TemplateDirIterator;
|
16 |
+
|
17 |
/**
|
18 |
* @author Fabien Potencier <fabien@symfony.com>
|
19 |
*
|
24 |
private $twig;
|
25 |
private $deprecations;
|
26 |
|
27 |
+
public function __construct(Environment $twig)
|
28 |
{
|
29 |
$this->twig = $twig;
|
30 |
}
|
39 |
*/
|
40 |
public function collectDir($dir, $ext = '.twig')
|
41 |
{
|
42 |
+
$iterator = new \RegexIterator(
|
43 |
+
new \RecursiveIteratorIterator(
|
44 |
+
new \RecursiveDirectoryIterator($dir), \RecursiveIteratorIterator::LEAVES_ONLY
|
45 |
), '{'.preg_quote($ext).'$}'
|
46 |
);
|
47 |
|
48 |
+
return $this->collect(new TemplateDirIterator($iterator));
|
49 |
}
|
50 |
|
51 |
/**
|
52 |
* Returns deprecations for passed templates.
|
53 |
*
|
54 |
+
* @param \Traversable $iterator An iterator of templates (where keys are template names and values the contents of the template)
|
55 |
*
|
56 |
* @return array An array of deprecations
|
57 |
*/
|
58 |
+
public function collect(\Traversable $iterator)
|
59 |
{
|
60 |
$this->deprecations = [];
|
61 |
|
63 |
|
64 |
foreach ($iterator as $name => $contents) {
|
65 |
try {
|
66 |
+
$this->twig->parse($this->twig->tokenize(new Source($contents, $name)));
|
67 |
+
} catch (SyntaxError $e) {
|
68 |
// ignore templates containing syntax errors
|
69 |
}
|
70 |
}
|
vendor/twig/twig/test/Twig/Tests/Cache/FilesystemTest.php
CHANGED
@@ -9,7 +9,9 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
-
|
|
|
|
|
13 |
|
14 |
class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase
|
15 |
{
|
@@ -22,7 +24,7 @@ class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase
|
|
22 |
$nonce = hash('sha256', uniqid(mt_rand(), true));
|
23 |
$this->classname = '__Twig_Tests_Cache_FilesystemTest_Template_'.$nonce;
|
24 |
$this->directory = sys_get_temp_dir().'/twig-test';
|
25 |
-
$this->cache = new
|
26 |
}
|
27 |
|
28 |
protected function tearDown()
|
@@ -36,7 +38,7 @@ class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase
|
|
36 |
{
|
37 |
$key = $this->directory.'/cache/cachefile.php';
|
38 |
|
39 |
-
$dir = dirname($key);
|
40 |
@mkdir($dir, 0777, true);
|
41 |
$this->assertTrue(is_dir($dir));
|
42 |
$this->assertFalse(class_exists($this->classname, false));
|
@@ -76,12 +78,12 @@ class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase
|
|
76 |
}
|
77 |
|
78 |
/**
|
79 |
-
* @expectedException RuntimeException
|
80 |
* @expectedExceptionMessage Unable to create the cache directory
|
81 |
*/
|
82 |
public function testWriteFailMkdir()
|
83 |
{
|
84 |
-
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
85 |
$this->markTestSkipped('Read-only directories not possible on Windows.');
|
86 |
}
|
87 |
|
@@ -98,12 +100,12 @@ class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase
|
|
98 |
}
|
99 |
|
100 |
/**
|
101 |
-
* @expectedException RuntimeException
|
102 |
* @expectedExceptionMessage Unable to write in the cache directory
|
103 |
*/
|
104 |
public function testWriteFailDirWritable()
|
105 |
{
|
106 |
-
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
107 |
$this->markTestSkipped('Read-only directories not possible on Windows.');
|
108 |
}
|
109 |
|
@@ -122,7 +124,7 @@ class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase
|
|
122 |
}
|
123 |
|
124 |
/**
|
125 |
-
* @expectedException RuntimeException
|
126 |
* @expectedExceptionMessage Failed to write cache file
|
127 |
*/
|
128 |
public function testWriteFailWriteFile()
|
@@ -143,7 +145,7 @@ class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase
|
|
143 |
{
|
144 |
$key = $this->directory.'/cache/cachefile.php';
|
145 |
|
146 |
-
$dir = dirname($key);
|
147 |
@mkdir($dir, 0777, true);
|
148 |
$this->assertTrue(is_dir($dir));
|
149 |
|
@@ -166,8 +168,8 @@ class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase
|
|
166 |
*/
|
167 |
public function testGenerateKey($expected, $input)
|
168 |
{
|
169 |
-
$cache = new
|
170 |
-
$this->assertRegExp($expected, $cache->generateKey('_test_', get_class($this)));
|
171 |
}
|
172 |
|
173 |
public function provideDirectories()
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Cache\FilesystemCache;
|
13 |
+
|
14 |
+
require_once \dirname(__DIR__).'/FilesystemHelper.php';
|
15 |
|
16 |
class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase
|
17 |
{
|
24 |
$nonce = hash('sha256', uniqid(mt_rand(), true));
|
25 |
$this->classname = '__Twig_Tests_Cache_FilesystemTest_Template_'.$nonce;
|
26 |
$this->directory = sys_get_temp_dir().'/twig-test';
|
27 |
+
$this->cache = new FilesystemCache($this->directory);
|
28 |
}
|
29 |
|
30 |
protected function tearDown()
|
38 |
{
|
39 |
$key = $this->directory.'/cache/cachefile.php';
|
40 |
|
41 |
+
$dir = \dirname($key);
|
42 |
@mkdir($dir, 0777, true);
|
43 |
$this->assertTrue(is_dir($dir));
|
44 |
$this->assertFalse(class_exists($this->classname, false));
|
78 |
}
|
79 |
|
80 |
/**
|
81 |
+
* @expectedException \RuntimeException
|
82 |
* @expectedExceptionMessage Unable to create the cache directory
|
83 |
*/
|
84 |
public function testWriteFailMkdir()
|
85 |
{
|
86 |
+
if (\defined('PHP_WINDOWS_VERSION_BUILD')) {
|
87 |
$this->markTestSkipped('Read-only directories not possible on Windows.');
|
88 |
}
|
89 |
|
100 |
}
|
101 |
|
102 |
/**
|
103 |
+
* @expectedException \RuntimeException
|
104 |
* @expectedExceptionMessage Unable to write in the cache directory
|
105 |
*/
|
106 |
public function testWriteFailDirWritable()
|
107 |
{
|
108 |
+
if (\defined('PHP_WINDOWS_VERSION_BUILD')) {
|
109 |
$this->markTestSkipped('Read-only directories not possible on Windows.');
|
110 |
}
|
111 |
|
124 |
}
|
125 |
|
126 |
/**
|
127 |
+
* @expectedException \RuntimeException
|
128 |
* @expectedExceptionMessage Failed to write cache file
|
129 |
*/
|
130 |
public function testWriteFailWriteFile()
|
145 |
{
|
146 |
$key = $this->directory.'/cache/cachefile.php';
|
147 |
|
148 |
+
$dir = \dirname($key);
|
149 |
@mkdir($dir, 0777, true);
|
150 |
$this->assertTrue(is_dir($dir));
|
151 |
|
168 |
*/
|
169 |
public function testGenerateKey($expected, $input)
|
170 |
{
|
171 |
+
$cache = new FilesystemCache($input);
|
172 |
+
$this->assertRegExp($expected, $cache->generateKey('_test_', \get_class($this)));
|
173 |
}
|
174 |
|
175 |
public function provideDirectories()
|
vendor/twig/twig/test/Twig/Tests/CompilerTest.php
CHANGED
@@ -9,11 +9,14 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
12 |
class Twig_Tests_CompilerTest extends \PHPUnit\Framework\TestCase
|
13 |
{
|
14 |
public function testReprNumericValueWithLocale()
|
15 |
{
|
16 |
-
$compiler = new
|
17 |
|
18 |
$locale = setlocale(LC_NUMERIC, 0);
|
19 |
if (false === $locale) {
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Compiler;
|
13 |
+
use Twig\Environment;
|
14 |
+
|
15 |
class Twig_Tests_CompilerTest extends \PHPUnit\Framework\TestCase
|
16 |
{
|
17 |
public function testReprNumericValueWithLocale()
|
18 |
{
|
19 |
+
$compiler = new Compiler(new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock()));
|
20 |
|
21 |
$locale = setlocale(LC_NUMERIC, 0);
|
22 |
if (false === $locale) {
|
vendor/twig/twig/test/Twig/Tests/ContainerRuntimeLoaderTest.php
CHANGED
@@ -9,6 +9,8 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
12 |
class Twig_Tests_ContainerRuntimeLoaderTest extends \PHPUnit\Framework\TestCase
|
13 |
{
|
14 |
/**
|
@@ -18,9 +20,9 @@ class Twig_Tests_ContainerRuntimeLoaderTest extends \PHPUnit\Framework\TestCase
|
|
18 |
{
|
19 |
$container = $this->getMockBuilder('Psr\Container\ContainerInterface')->getMock();
|
20 |
$container->expects($this->once())->method('has')->with('stdClass')->willReturn(true);
|
21 |
-
$container->expects($this->once())->method('get')->with('stdClass')->willReturn(new stdClass());
|
22 |
|
23 |
-
$loader = new
|
24 |
|
25 |
$this->assertInstanceOf('stdClass', $loader->load('stdClass'));
|
26 |
}
|
@@ -34,7 +36,7 @@ class Twig_Tests_ContainerRuntimeLoaderTest extends \PHPUnit\Framework\TestCase
|
|
34 |
$container->expects($this->once())->method('has')->with('Foo');
|
35 |
$container->expects($this->never())->method('get');
|
36 |
|
37 |
-
$loader = new
|
38 |
$this->assertNull($loader->load('Foo'));
|
39 |
}
|
40 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\RuntimeLoader\ContainerRuntimeLoader;
|
13 |
+
|
14 |
class Twig_Tests_ContainerRuntimeLoaderTest extends \PHPUnit\Framework\TestCase
|
15 |
{
|
16 |
/**
|
20 |
{
|
21 |
$container = $this->getMockBuilder('Psr\Container\ContainerInterface')->getMock();
|
22 |
$container->expects($this->once())->method('has')->with('stdClass')->willReturn(true);
|
23 |
+
$container->expects($this->once())->method('get')->with('stdClass')->willReturn(new \stdClass());
|
24 |
|
25 |
+
$loader = new ContainerRuntimeLoader($container);
|
26 |
|
27 |
$this->assertInstanceOf('stdClass', $loader->load('stdClass'));
|
28 |
}
|
36 |
$container->expects($this->once())->method('has')->with('Foo');
|
37 |
$container->expects($this->never())->method('get');
|
38 |
|
39 |
+
$loader = new ContainerRuntimeLoader($container);
|
40 |
$this->assertNull($loader->load('Foo'));
|
41 |
}
|
42 |
}
|
vendor/twig/twig/test/Twig/Tests/CustomExtensionTest.php
CHANGED
@@ -9,13 +9,16 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
12 |
class CustomExtensionTest extends \PHPUnit\Framework\TestCase
|
13 |
{
|
14 |
/**
|
15 |
* @requires PHP 5.3
|
16 |
* @dataProvider provideInvalidExtensions
|
17 |
*/
|
18 |
-
public function testGetInvalidOperators(
|
19 |
{
|
20 |
if (method_exists($this, 'expectException')) {
|
21 |
$this->expectException('InvalidArgumentException');
|
@@ -24,7 +27,7 @@ class CustomExtensionTest extends \PHPUnit\Framework\TestCase
|
|
24 |
$this->setExpectedException('InvalidArgumentException', $expectedExceptionMessage);
|
25 |
}
|
26 |
|
27 |
-
$env = new
|
28 |
$env->addExtension($extension);
|
29 |
$env->getUnaryOperators();
|
30 |
}
|
@@ -32,13 +35,13 @@ class CustomExtensionTest extends \PHPUnit\Framework\TestCase
|
|
32 |
public function provideInvalidExtensions()
|
33 |
{
|
34 |
return [
|
35 |
-
[new InvalidOperatorExtension(new stdClass()), '"InvalidOperatorExtension::getOperators()" must return an array with operators, got "stdClass".'],
|
36 |
[new InvalidOperatorExtension([1, 2, 3]), '"InvalidOperatorExtension::getOperators()" must return an array of 2 elements, got 3.'],
|
37 |
];
|
38 |
}
|
39 |
}
|
40 |
|
41 |
-
class InvalidOperatorExtension implements
|
42 |
{
|
43 |
private $operators;
|
44 |
|
@@ -47,7 +50,7 @@ class InvalidOperatorExtension implements Twig_ExtensionInterface
|
|
47 |
$this->operators = $operators;
|
48 |
}
|
49 |
|
50 |
-
public function initRuntime(
|
51 |
{
|
52 |
}
|
53 |
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Environment;
|
13 |
+
use Twig\Extension\ExtensionInterface;
|
14 |
+
|
15 |
class CustomExtensionTest extends \PHPUnit\Framework\TestCase
|
16 |
{
|
17 |
/**
|
18 |
* @requires PHP 5.3
|
19 |
* @dataProvider provideInvalidExtensions
|
20 |
*/
|
21 |
+
public function testGetInvalidOperators(ExtensionInterface $extension, $expectedExceptionMessage)
|
22 |
{
|
23 |
if (method_exists($this, 'expectException')) {
|
24 |
$this->expectException('InvalidArgumentException');
|
27 |
$this->setExpectedException('InvalidArgumentException', $expectedExceptionMessage);
|
28 |
}
|
29 |
|
30 |
+
$env = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock());
|
31 |
$env->addExtension($extension);
|
32 |
$env->getUnaryOperators();
|
33 |
}
|
35 |
public function provideInvalidExtensions()
|
36 |
{
|
37 |
return [
|
38 |
+
[new InvalidOperatorExtension(new \stdClass()), '"InvalidOperatorExtension::getOperators()" must return an array with operators, got "stdClass".'],
|
39 |
[new InvalidOperatorExtension([1, 2, 3]), '"InvalidOperatorExtension::getOperators()" must return an array of 2 elements, got 3.'],
|
40 |
];
|
41 |
}
|
42 |
}
|
43 |
|
44 |
+
class InvalidOperatorExtension implements ExtensionInterface
|
45 |
{
|
46 |
private $operators;
|
47 |
|
50 |
$this->operators = $operators;
|
51 |
}
|
52 |
|
53 |
+
public function initRuntime(Environment $environment)
|
54 |
{
|
55 |
}
|
56 |
|
vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php
CHANGED
@@ -9,7 +9,22 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
15 |
{
|
@@ -20,7 +35,7 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
20 |
*/
|
21 |
public function testLegacyTokenizeSignature()
|
22 |
{
|
23 |
-
$env = new
|
24 |
$stream = $env->tokenize('{{ foo }}', 'foo');
|
25 |
$this->assertEquals('{{ foo }}', $stream->getSource());
|
26 |
$this->assertEquals('foo', $stream->getFilename());
|
@@ -31,30 +46,30 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
31 |
*/
|
32 |
public function testLegacyCompileSourceSignature()
|
33 |
{
|
34 |
-
$loader = new
|
35 |
-
$env = new
|
36 |
$this->assertContains('getTemplateName', $env->compileSource('{{ foo }}', 'foo'));
|
37 |
}
|
38 |
|
39 |
/**
|
40 |
-
* @expectedException LogicException
|
41 |
* @expectedExceptionMessage You must set a loader first.
|
42 |
* @group legacy
|
43 |
*/
|
44 |
public function testRenderNoLoader()
|
45 |
{
|
46 |
-
$env = new
|
47 |
$env->render('test');
|
48 |
}
|
49 |
|
50 |
public function testAutoescapeOption()
|
51 |
{
|
52 |
-
$loader = new
|
53 |
'html' => '{{ foo }} {{ foo }}',
|
54 |
'js' => '{{ bar }} {{ bar }}',
|
55 |
]);
|
56 |
|
57 |
-
$twig = new
|
58 |
'debug' => true,
|
59 |
'cache' => false,
|
60 |
'autoescape' => [$this, 'escapingStrategyCallback'],
|
@@ -73,12 +88,12 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
73 |
{
|
74 |
// to be removed in 2.0
|
75 |
$loader = $this->getMockBuilder('Twig_EnvironmentTestLoaderInterface')->getMock();
|
76 |
-
//$loader = $this->getMockBuilder(['
|
77 |
-
$loader->expects($this->any())->method('getSourceContext')->will($this->returnValue(new
|
78 |
|
79 |
// globals can be added after calling getGlobals
|
80 |
|
81 |
-
$twig = new
|
82 |
$twig->addGlobal('foo', 'foo');
|
83 |
$twig->getGlobals();
|
84 |
$twig->addGlobal('foo', 'bar');
|
@@ -86,7 +101,7 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
86 |
$this->assertEquals('bar', $globals['foo']);
|
87 |
|
88 |
// globals can be modified after a template has been loaded
|
89 |
-
$twig = new
|
90 |
$twig->addGlobal('foo', 'foo');
|
91 |
$twig->getGlobals();
|
92 |
$twig->loadTemplate('index');
|
@@ -95,7 +110,7 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
95 |
$this->assertEquals('bar', $globals['foo']);
|
96 |
|
97 |
// globals can be modified after extensions init
|
98 |
-
$twig = new
|
99 |
$twig->addGlobal('foo', 'foo');
|
100 |
$twig->getGlobals();
|
101 |
$twig->getFunctions();
|
@@ -104,8 +119,8 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
104 |
$this->assertEquals('bar', $globals['foo']);
|
105 |
|
106 |
// globals can be modified after extensions and a template has been loaded
|
107 |
-
$arrayLoader = new
|
108 |
-
$twig = new
|
109 |
$twig->addGlobal('foo', 'foo');
|
110 |
$twig->getGlobals();
|
111 |
$twig->getFunctions();
|
@@ -114,7 +129,7 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
114 |
$globals = $twig->getGlobals();
|
115 |
$this->assertEquals('bar', $globals['foo']);
|
116 |
|
117 |
-
$twig = new
|
118 |
$twig->getGlobals();
|
119 |
$twig->addGlobal('foo', 'bar');
|
120 |
$template = $twig->loadTemplate('index');
|
@@ -122,31 +137,31 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
122 |
|
123 |
/* to be uncomment in Twig 2.0
|
124 |
// globals cannot be added after a template has been loaded
|
125 |
-
$twig = new
|
126 |
$twig->addGlobal('foo', 'foo');
|
127 |
$twig->getGlobals();
|
128 |
$twig->loadTemplate('index');
|
129 |
try {
|
130 |
$twig->addGlobal('bar', 'bar');
|
131 |
$this->fail();
|
132 |
-
} catch (LogicException $e) {
|
133 |
$this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
|
134 |
}
|
135 |
|
136 |
// globals cannot be added after extensions init
|
137 |
-
$twig = new
|
138 |
$twig->addGlobal('foo', 'foo');
|
139 |
$twig->getGlobals();
|
140 |
$twig->getFunctions();
|
141 |
try {
|
142 |
$twig->addGlobal('bar', 'bar');
|
143 |
$this->fail();
|
144 |
-
} catch (LogicException $e) {
|
145 |
$this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
|
146 |
}
|
147 |
|
148 |
// globals cannot be added after extensions and a template has been loaded
|
149 |
-
$twig = new
|
150 |
$twig->addGlobal('foo', 'foo');
|
151 |
$twig->getGlobals();
|
152 |
$twig->getFunctions();
|
@@ -154,17 +169,17 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
154 |
try {
|
155 |
$twig->addGlobal('bar', 'bar');
|
156 |
$this->fail();
|
157 |
-
} catch (LogicException $e) {
|
158 |
$this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
|
159 |
}
|
160 |
|
161 |
// test adding globals after a template has been loaded without call to getGlobals
|
162 |
-
$twig = new
|
163 |
$twig->loadTemplate('index');
|
164 |
try {
|
165 |
$twig->addGlobal('bar', 'bar');
|
166 |
$this->fail();
|
167 |
-
} catch (LogicException $e) {
|
168 |
$this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
|
169 |
}
|
170 |
*/
|
@@ -172,18 +187,18 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
172 |
|
173 |
public function testExtensionsAreNotInitializedWhenRenderingACompiledTemplate()
|
174 |
{
|
175 |
-
$cache = new
|
176 |
$options = ['cache' => $cache, 'auto_reload' => false, 'debug' => false];
|
177 |
|
178 |
// force compilation
|
179 |
-
$twig = new
|
180 |
|
181 |
$key = $cache->generateKey('index', $twig->getTemplateClass('index'));
|
182 |
-
$cache->write($key, $twig->compileSource(new
|
183 |
|
184 |
// check that extensions won't be initialized when rendering a template that is already in the cache
|
185 |
$twig = $this
|
186 |
-
->getMockBuilder('
|
187 |
->setConstructorArgs([$loader, $options])
|
188 |
->setMethods(['initExtensions'])
|
189 |
->getMock()
|
@@ -203,9 +218,9 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
203 |
$templateName = __FUNCTION__;
|
204 |
$templateContent = __FUNCTION__;
|
205 |
|
206 |
-
$cache = $this->getMockBuilder('
|
207 |
$loader = $this->getMockLoader($templateName, $templateContent);
|
208 |
-
$twig = new
|
209 |
|
210 |
// Cache miss: getTimestamp returns 0 and as a result the load() is
|
211 |
// skipped.
|
@@ -230,9 +245,9 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
230 |
$templateName = __FUNCTION__;
|
231 |
$templateContent = __FUNCTION__;
|
232 |
|
233 |
-
$cache = $this->getMockBuilder('
|
234 |
$loader = $this->getMockLoader($templateName, $templateContent);
|
235 |
-
$twig = new
|
236 |
|
237 |
$now = time();
|
238 |
|
@@ -258,9 +273,9 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
258 |
$templateName = __FUNCTION__;
|
259 |
$templateContent = __FUNCTION__;
|
260 |
|
261 |
-
$cache = $this->getMockBuilder('
|
262 |
$loader = $this->getMockLoader($templateName, $templateContent);
|
263 |
-
$twig = new
|
264 |
|
265 |
$now = time();
|
266 |
|
@@ -286,7 +301,7 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
286 |
*/
|
287 |
public function testHasGetExtensionWithDynamicName()
|
288 |
{
|
289 |
-
$twig = new
|
290 |
|
291 |
$ext1 = new Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName('ext1');
|
292 |
$ext2 = new Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName('ext2');
|
@@ -304,7 +319,7 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
304 |
|
305 |
public function testHasGetExtensionByClassName()
|
306 |
{
|
307 |
-
$twig = new
|
308 |
$twig->addExtension($ext = new Twig_Tests_EnvironmentTest_Extension());
|
309 |
$this->assertTrue($twig->hasExtension('Twig_Tests_EnvironmentTest_Extension'));
|
310 |
$this->assertTrue($twig->hasExtension('\Twig_Tests_EnvironmentTest_Extension'));
|
@@ -318,7 +333,7 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
318 |
|
319 |
public function testAddExtension()
|
320 |
{
|
321 |
-
$twig = new
|
322 |
$twig->addExtension(new Twig_Tests_EnvironmentTest_Extension());
|
323 |
|
324 |
$this->assertArrayHasKey('test', $twig->getTags());
|
@@ -343,7 +358,7 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
343 |
*/
|
344 |
public function testAddExtensionWithDeprecatedGetGlobals()
|
345 |
{
|
346 |
-
$twig = new
|
347 |
$twig->addExtension(new Twig_Tests_EnvironmentTest_Extension_WithGlobals());
|
348 |
|
349 |
$this->deprecations = [];
|
@@ -362,7 +377,7 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
362 |
*/
|
363 |
public function testRemoveExtension()
|
364 |
{
|
365 |
-
$twig = new
|
366 |
$twig->addExtension(new Twig_Tests_EnvironmentTest_Extension_WithDeprecatedName());
|
367 |
$twig->removeExtension('environment_test');
|
368 |
|
@@ -379,27 +394,29 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
|
379 |
public function testAddMockExtension()
|
380 |
{
|
381 |
// should be replaced by the following in 2.0 (this current code is just to avoid a dep notice)
|
382 |
-
// $extension = $this->getMockBuilder('
|
383 |
$extension = eval(<<<EOF
|
384 |
-
|
|
|
|
|
385 |
{
|
386 |
}
|
387 |
EOF
|
388 |
);
|
389 |
$extension = new Twig_Tests_EnvironmentTest_ExtensionInEval();
|
390 |
|
391 |
-
$loader = new
|
392 |
|
393 |
-
$twig = new
|
394 |
$twig->addExtension($extension);
|
395 |
|
396 |
-
$this->assertInstanceOf('
|
397 |
$this->assertTrue($twig->isTemplateFresh('page', time()));
|
398 |
}
|
399 |
|
400 |
public function testInitRuntimeWithAnExtensionUsingInitRuntimeNoDeprecation()
|
401 |
{
|
402 |
-
$twig = new
|
403 |
$twig->addExtension(new Twig_Tests_EnvironmentTest_ExtensionWithoutDeprecationInitRuntime());
|
404 |
$twig->initRuntime();
|
405 |
|
@@ -413,7 +430,7 @@ EOF
|
|
413 |
*/
|
414 |
public function testInitRuntimeWithAnExtensionUsingInitRuntimeDeprecation()
|
415 |
{
|
416 |
-
$twig = new
|
417 |
$twig->addExtension(new Twig_Tests_EnvironmentTest_ExtensionWithDeprecationInitRuntime());
|
418 |
|
419 |
$this->deprecations = [];
|
@@ -439,7 +456,7 @@ EOF
|
|
439 |
*/
|
440 |
public function testOverrideExtension()
|
441 |
{
|
442 |
-
$twig = new
|
443 |
$twig->addExtension(new Twig_Tests_EnvironmentTest_ExtensionWithDeprecationInitRuntime());
|
444 |
|
445 |
$this->deprecations = [];
|
@@ -456,10 +473,10 @@ EOF
|
|
456 |
|
457 |
public function testAddRuntimeLoader()
|
458 |
{
|
459 |
-
$runtimeLoader = $this->getMockBuilder('
|
460 |
$runtimeLoader->expects($this->any())->method('load')->will($this->returnValue(new Twig_Tests_EnvironmentTest_Runtime()));
|
461 |
|
462 |
-
$loader = new
|
463 |
'func_array' => '{{ from_runtime_array("foo") }}',
|
464 |
'func_array_default' => '{{ from_runtime_array() }}',
|
465 |
'func_array_named_args' => '{{ from_runtime_array(name="foo") }}',
|
@@ -468,7 +485,7 @@ EOF
|
|
468 |
'func_string_named_args' => '{{ from_runtime_string(name="foo") }}',
|
469 |
]);
|
470 |
|
471 |
-
$twig = new
|
472 |
$twig->addExtension(new Twig_Tests_EnvironmentTest_ExtensionWithoutRuntime());
|
473 |
$twig->addRuntimeLoader($runtimeLoader);
|
474 |
|
@@ -481,12 +498,12 @@ EOF
|
|
481 |
}
|
482 |
|
483 |
/**
|
484 |
-
* @expectedException
|
485 |
* @expectedExceptionMessage Circular reference detected for Twig template "base.html.twig", path: base.html.twig -> base.html.twig in "base.html.twig" at line 1
|
486 |
*/
|
487 |
public function testFailLoadTemplateOnCircularReference()
|
488 |
{
|
489 |
-
$twig = new
|
490 |
'base.html.twig' => '{% extends "base.html.twig" %}',
|
491 |
]));
|
492 |
|
@@ -494,12 +511,12 @@ EOF
|
|
494 |
}
|
495 |
|
496 |
/**
|
497 |
-
* @expectedException
|
498 |
* @expectedExceptionMessage Circular reference detected for Twig template "base1.html.twig", path: base1.html.twig -> base2.html.twig -> base1.html.twig in "base1.html.twig" at line 1
|
499 |
*/
|
500 |
public function testFailLoadTemplateOnComplexCircularReference()
|
501 |
{
|
502 |
-
$twig = new
|
503 |
'base1.html.twig' => '{% extends "base2.html.twig" %}',
|
504 |
'base2.html.twig' => '{% extends "base1.html.twig" %}',
|
505 |
]));
|
@@ -511,11 +528,11 @@ EOF
|
|
511 |
{
|
512 |
// to be removed in 2.0
|
513 |
$loader = $this->getMockBuilder('Twig_EnvironmentTestLoaderInterface')->getMock();
|
514 |
-
//$loader = $this->getMockBuilder(['
|
515 |
$loader->expects($this->any())
|
516 |
->method('getSourceContext')
|
517 |
->with($templateName)
|
518 |
-
->will($this->returnValue(new
|
519 |
$loader->expects($this->any())
|
520 |
->method('getCacheKey')
|
521 |
->with($templateName)
|
@@ -525,7 +542,7 @@ EOF
|
|
525 |
}
|
526 |
}
|
527 |
|
528 |
-
class Twig_Tests_EnvironmentTest_Extension_WithGlobals extends
|
529 |
{
|
530 |
public function getGlobals()
|
531 |
{
|
@@ -535,7 +552,7 @@ class Twig_Tests_EnvironmentTest_Extension_WithGlobals extends Twig_Extension
|
|
535 |
}
|
536 |
}
|
537 |
|
538 |
-
class Twig_Tests_EnvironmentTest_Extension extends
|
539 |
{
|
540 |
public function getTokenParsers()
|
541 |
{
|
@@ -554,21 +571,21 @@ class Twig_Tests_EnvironmentTest_Extension extends Twig_Extension implements Twi
|
|
554 |
public function getFilters()
|
555 |
{
|
556 |
return [
|
557 |
-
new
|
558 |
];
|
559 |
}
|
560 |
|
561 |
public function getTests()
|
562 |
{
|
563 |
return [
|
564 |
-
new
|
565 |
];
|
566 |
}
|
567 |
|
568 |
public function getFunctions()
|
569 |
{
|
570 |
return [
|
571 |
-
new
|
572 |
];
|
573 |
}
|
574 |
|
@@ -589,7 +606,7 @@ class Twig_Tests_EnvironmentTest_Extension extends Twig_Extension implements Twi
|
|
589 |
}
|
590 |
class_alias('Twig_Tests_EnvironmentTest_Extension', 'Twig\Tests\EnvironmentTest\Extension', false);
|
591 |
|
592 |
-
class Twig_Tests_EnvironmentTest_Extension_WithDeprecatedName extends
|
593 |
{
|
594 |
public function getName()
|
595 |
{
|
@@ -597,7 +614,7 @@ class Twig_Tests_EnvironmentTest_Extension_WithDeprecatedName extends Twig_Exten
|
|
597 |
}
|
598 |
}
|
599 |
|
600 |
-
class Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName extends
|
601 |
{
|
602 |
private $name;
|
603 |
|
@@ -612,9 +629,9 @@ class Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName extends Twi
|
|
612 |
}
|
613 |
}
|
614 |
|
615 |
-
class Twig_Tests_EnvironmentTest_TokenParser extends
|
616 |
{
|
617 |
-
public function parse(
|
618 |
{
|
619 |
}
|
620 |
|
@@ -624,14 +641,14 @@ class Twig_Tests_EnvironmentTest_TokenParser extends Twig_TokenParser
|
|
624 |
}
|
625 |
}
|
626 |
|
627 |
-
class Twig_Tests_EnvironmentTest_NodeVisitor implements
|
628 |
{
|
629 |
-
public function enterNode(Twig_NodeInterface $node,
|
630 |
{
|
631 |
return $node;
|
632 |
}
|
633 |
|
634 |
-
public function leaveNode(Twig_NodeInterface $node,
|
635 |
{
|
636 |
return $node;
|
637 |
}
|
@@ -642,27 +659,27 @@ class Twig_Tests_EnvironmentTest_NodeVisitor implements Twig_NodeVisitorInterfac
|
|
642 |
}
|
643 |
}
|
644 |
|
645 |
-
class Twig_Tests_EnvironmentTest_ExtensionWithDeprecationInitRuntime extends
|
646 |
{
|
647 |
-
public function initRuntime(
|
648 |
{
|
649 |
}
|
650 |
}
|
651 |
|
652 |
-
class Twig_Tests_EnvironmentTest_ExtensionWithoutDeprecationInitRuntime extends
|
653 |
{
|
654 |
-
public function initRuntime(
|
655 |
{
|
656 |
}
|
657 |
}
|
658 |
|
659 |
-
class Twig_Tests_EnvironmentTest_ExtensionWithoutRuntime extends
|
660 |
{
|
661 |
public function getFunctions()
|
662 |
{
|
663 |
return [
|
664 |
-
new
|
665 |
-
new
|
666 |
];
|
667 |
}
|
668 |
|
@@ -681,6 +698,6 @@ class Twig_Tests_EnvironmentTest_Runtime
|
|
681 |
}
|
682 |
|
683 |
// to be removed in 2.0
|
684 |
-
interface Twig_EnvironmentTestLoaderInterface extends
|
685 |
{
|
686 |
}
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Cache\FilesystemCache;
|
13 |
+
use Twig\Environment;
|
14 |
+
use Twig\Extension\AbstractExtension;
|
15 |
+
use Twig\Extension\GlobalsInterface;
|
16 |
+
use Twig\Extension\InitRuntimeInterface;
|
17 |
+
use Twig\Loader\ArrayLoader;
|
18 |
+
use Twig\Loader\LoaderInterface;
|
19 |
+
use Twig\NodeVisitor\NodeVisitorInterface;
|
20 |
+
use Twig\Source;
|
21 |
+
use Twig\Token;
|
22 |
+
use Twig\TokenParser\AbstractTokenParser;
|
23 |
+
use Twig\TwigFilter;
|
24 |
+
use Twig\TwigFunction;
|
25 |
+
use Twig\TwigTest;
|
26 |
+
|
27 |
+
require_once __DIR__.'/FilesystemHelper.php';
|
28 |
|
29 |
class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase
|
30 |
{
|
35 |
*/
|
36 |
public function testLegacyTokenizeSignature()
|
37 |
{
|
38 |
+
$env = new Environment();
|
39 |
$stream = $env->tokenize('{{ foo }}', 'foo');
|
40 |
$this->assertEquals('{{ foo }}', $stream->getSource());
|
41 |
$this->assertEquals('foo', $stream->getFilename());
|
46 |
*/
|
47 |
public function testLegacyCompileSourceSignature()
|
48 |
{
|
49 |
+
$loader = new ArrayLoader(['foo' => '{{ foo }}']);
|
50 |
+
$env = new Environment($loader);
|
51 |
$this->assertContains('getTemplateName', $env->compileSource('{{ foo }}', 'foo'));
|
52 |
}
|
53 |
|
54 |
/**
|
55 |
+
* @expectedException \LogicException
|
56 |
* @expectedExceptionMessage You must set a loader first.
|
57 |
* @group legacy
|
58 |
*/
|
59 |
public function testRenderNoLoader()
|
60 |
{
|
61 |
+
$env = new Environment();
|
62 |
$env->render('test');
|
63 |
}
|
64 |
|
65 |
public function testAutoescapeOption()
|
66 |
{
|
67 |
+
$loader = new ArrayLoader([
|
68 |
'html' => '{{ foo }} {{ foo }}',
|
69 |
'js' => '{{ bar }} {{ bar }}',
|
70 |
]);
|
71 |
|
72 |
+
$twig = new Environment($loader, [
|
73 |
'debug' => true,
|
74 |
'cache' => false,
|
75 |
'autoescape' => [$this, 'escapingStrategyCallback'],
|
88 |
{
|
89 |
// to be removed in 2.0
|
90 |
$loader = $this->getMockBuilder('Twig_EnvironmentTestLoaderInterface')->getMock();
|
91 |
+
//$loader = $this->getMockBuilder(['\Twig\Loader\LoaderInterface', '\Twig\Loader\SourceContextLoaderInterface'])->getMock();
|
92 |
+
$loader->expects($this->any())->method('getSourceContext')->will($this->returnValue(new Source('', '')));
|
93 |
|
94 |
// globals can be added after calling getGlobals
|
95 |
|
96 |
+
$twig = new Environment($loader);
|
97 |
$twig->addGlobal('foo', 'foo');
|
98 |
$twig->getGlobals();
|
99 |
$twig->addGlobal('foo', 'bar');
|
101 |
$this->assertEquals('bar', $globals['foo']);
|
102 |
|
103 |
// globals can be modified after a template has been loaded
|
104 |
+
$twig = new Environment($loader);
|
105 |
$twig->addGlobal('foo', 'foo');
|
106 |
$twig->getGlobals();
|
107 |
$twig->loadTemplate('index');
|
110 |
$this->assertEquals('bar', $globals['foo']);
|
111 |
|
112 |
// globals can be modified after extensions init
|
113 |
+
$twig = new Environment($loader);
|
114 |
$twig->addGlobal('foo', 'foo');
|
115 |
$twig->getGlobals();
|
116 |
$twig->getFunctions();
|
119 |
$this->assertEquals('bar', $globals['foo']);
|
120 |
|
121 |
// globals can be modified after extensions and a template has been loaded
|
122 |
+
$arrayLoader = new ArrayLoader(['index' => '{{foo}}']);
|
123 |
+
$twig = new Environment($arrayLoader);
|
124 |
$twig->addGlobal('foo', 'foo');
|
125 |
$twig->getGlobals();
|
126 |
$twig->getFunctions();
|
129 |
$globals = $twig->getGlobals();
|
130 |
$this->assertEquals('bar', $globals['foo']);
|
131 |
|
132 |
+
$twig = new Environment($arrayLoader);
|
133 |
$twig->getGlobals();
|
134 |
$twig->addGlobal('foo', 'bar');
|
135 |
$template = $twig->loadTemplate('index');
|
137 |
|
138 |
/* to be uncomment in Twig 2.0
|
139 |
// globals cannot be added after a template has been loaded
|
140 |
+
$twig = new Environment($loader);
|
141 |
$twig->addGlobal('foo', 'foo');
|
142 |
$twig->getGlobals();
|
143 |
$twig->loadTemplate('index');
|
144 |
try {
|
145 |
$twig->addGlobal('bar', 'bar');
|
146 |
$this->fail();
|
147 |
+
} catch (\LogicException $e) {
|
148 |
$this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
|
149 |
}
|
150 |
|
151 |
// globals cannot be added after extensions init
|
152 |
+
$twig = new Environment($loader);
|
153 |
$twig->addGlobal('foo', 'foo');
|
154 |
$twig->getGlobals();
|
155 |
$twig->getFunctions();
|
156 |
try {
|
157 |
$twig->addGlobal('bar', 'bar');
|
158 |
$this->fail();
|
159 |
+
} catch (\LogicException $e) {
|
160 |
$this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
|
161 |
}
|
162 |
|
163 |
// globals cannot be added after extensions and a template has been loaded
|
164 |
+
$twig = new Environment($loader);
|
165 |
$twig->addGlobal('foo', 'foo');
|
166 |
$twig->getGlobals();
|
167 |
$twig->getFunctions();
|
169 |
try {
|
170 |
$twig->addGlobal('bar', 'bar');
|
171 |
$this->fail();
|
172 |
+
} catch (\LogicException $e) {
|
173 |
$this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
|
174 |
}
|
175 |
|
176 |
// test adding globals after a template has been loaded without call to getGlobals
|
177 |
+
$twig = new Environment($loader);
|
178 |
$twig->loadTemplate('index');
|
179 |
try {
|
180 |
$twig->addGlobal('bar', 'bar');
|
181 |
$this->fail();
|
182 |
+
} catch (\LogicException $e) {
|
183 |
$this->assertFalse(array_key_exists('bar', $twig->getGlobals()));
|
184 |
}
|
185 |
*/
|
187 |
|
188 |
public function testExtensionsAreNotInitializedWhenRenderingACompiledTemplate()
|
189 |
{
|
190 |
+
$cache = new FilesystemCache($dir = sys_get_temp_dir().'/twig');
|
191 |
$options = ['cache' => $cache, 'auto_reload' => false, 'debug' => false];
|
192 |
|
193 |
// force compilation
|
194 |
+
$twig = new Environment($loader = new ArrayLoader(['index' => '{{ foo }}']), $options);
|
195 |
|
196 |
$key = $cache->generateKey('index', $twig->getTemplateClass('index'));
|
197 |
+
$cache->write($key, $twig->compileSource(new Source('{{ foo }}', 'index')));
|
198 |
|
199 |
// check that extensions won't be initialized when rendering a template that is already in the cache
|
200 |
$twig = $this
|
201 |
+
->getMockBuilder('\Twig\Environment')
|
202 |
->setConstructorArgs([$loader, $options])
|
203 |
->setMethods(['initExtensions'])
|
204 |
->getMock()
|
218 |
$templateName = __FUNCTION__;
|
219 |
$templateContent = __FUNCTION__;
|
220 |
|
221 |
+
$cache = $this->getMockBuilder('\Twig\Cache\CacheInterface')->getMock();
|
222 |
$loader = $this->getMockLoader($templateName, $templateContent);
|
223 |
+
$twig = new Environment($loader, ['cache' => $cache, 'auto_reload' => true, 'debug' => false]);
|
224 |
|
225 |
// Cache miss: getTimestamp returns 0 and as a result the load() is
|
226 |
// skipped.
|
245 |
$templateName = __FUNCTION__;
|
246 |
$templateContent = __FUNCTION__;
|
247 |
|
248 |
+
$cache = $this->getMockBuilder('\Twig\Cache\CacheInterface')->getMock();
|
249 |
$loader = $this->getMockLoader($templateName, $templateContent);
|
250 |
+
$twig = new Environment($loader, ['cache' => $cache, 'auto_reload' => true, 'debug' => false]);
|
251 |
|
252 |
$now = time();
|
253 |
|
273 |
$templateName = __FUNCTION__;
|
274 |
$templateContent = __FUNCTION__;
|
275 |
|
276 |
+
$cache = $this->getMockBuilder('\Twig\Cache\CacheInterface')->getMock();
|
277 |
$loader = $this->getMockLoader($templateName, $templateContent);
|
278 |
+
$twig = new Environment($loader, ['cache' => $cache, 'auto_reload' => true, 'debug' => false]);
|
279 |
|
280 |
$now = time();
|
281 |
|
301 |
*/
|
302 |
public function testHasGetExtensionWithDynamicName()
|
303 |
{
|
304 |
+
$twig = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock());
|
305 |
|
306 |
$ext1 = new Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName('ext1');
|
307 |
$ext2 = new Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName('ext2');
|
319 |
|
320 |
public function testHasGetExtensionByClassName()
|
321 |
{
|
322 |
+
$twig = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock());
|
323 |
$twig->addExtension($ext = new Twig_Tests_EnvironmentTest_Extension());
|
324 |
$this->assertTrue($twig->hasExtension('Twig_Tests_EnvironmentTest_Extension'));
|
325 |
$this->assertTrue($twig->hasExtension('\Twig_Tests_EnvironmentTest_Extension'));
|
333 |
|
334 |
public function testAddExtension()
|
335 |
{
|
336 |
+
$twig = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock());
|
337 |
$twig->addExtension(new Twig_Tests_EnvironmentTest_Extension());
|
338 |
|
339 |
$this->assertArrayHasKey('test', $twig->getTags());
|
358 |
*/
|
359 |
public function testAddExtensionWithDeprecatedGetGlobals()
|
360 |
{
|
361 |
+
$twig = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock());
|
362 |
$twig->addExtension(new Twig_Tests_EnvironmentTest_Extension_WithGlobals());
|
363 |
|
364 |
$this->deprecations = [];
|
377 |
*/
|
378 |
public function testRemoveExtension()
|
379 |
{
|
380 |
+
$twig = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock());
|
381 |
$twig->addExtension(new Twig_Tests_EnvironmentTest_Extension_WithDeprecatedName());
|
382 |
$twig->removeExtension('environment_test');
|
383 |
|
394 |
public function testAddMockExtension()
|
395 |
{
|
396 |
// should be replaced by the following in 2.0 (this current code is just to avoid a dep notice)
|
397 |
+
// $extension = $this->getMockBuilder('\Twig\Extension\AbstractExtension')->getMock();
|
398 |
$extension = eval(<<<EOF
|
399 |
+
use Twig\Extension\AbstractExtension;
|
400 |
+
|
401 |
+
class Twig_Tests_EnvironmentTest_ExtensionInEval extends AbstractExtension
|
402 |
{
|
403 |
}
|
404 |
EOF
|
405 |
);
|
406 |
$extension = new Twig_Tests_EnvironmentTest_ExtensionInEval();
|
407 |
|
408 |
+
$loader = new ArrayLoader(['page' => 'hey']);
|
409 |
|
410 |
+
$twig = new Environment($loader);
|
411 |
$twig->addExtension($extension);
|
412 |
|
413 |
+
$this->assertInstanceOf('\Twig\Extension\ExtensionInterface', $twig->getExtension(\get_class($extension)));
|
414 |
$this->assertTrue($twig->isTemplateFresh('page', time()));
|
415 |
}
|
416 |
|
417 |
public function testInitRuntimeWithAnExtensionUsingInitRuntimeNoDeprecation()
|
418 |
{
|
419 |
+
$twig = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock());
|
420 |
$twig->addExtension(new Twig_Tests_EnvironmentTest_ExtensionWithoutDeprecationInitRuntime());
|
421 |
$twig->initRuntime();
|
422 |
|
430 |
*/
|
431 |
public function testInitRuntimeWithAnExtensionUsingInitRuntimeDeprecation()
|
432 |
{
|
433 |
+
$twig = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock());
|
434 |
$twig->addExtension(new Twig_Tests_EnvironmentTest_ExtensionWithDeprecationInitRuntime());
|
435 |
|
436 |
$this->deprecations = [];
|
456 |
*/
|
457 |
public function testOverrideExtension()
|
458 |
{
|
459 |
+
$twig = new Environment($this->getMockBuilder('\Twig\Loader\LoaderInterface')->getMock());
|
460 |
$twig->addExtension(new Twig_Tests_EnvironmentTest_ExtensionWithDeprecationInitRuntime());
|
461 |
|
462 |
$this->deprecations = [];
|
473 |
|
474 |
public function testAddRuntimeLoader()
|
475 |
{
|
476 |
+
$runtimeLoader = $this->getMockBuilder('\Twig\RuntimeLoader\RuntimeLoaderInterface')->getMock();
|
477 |
$runtimeLoader->expects($this->any())->method('load')->will($this->returnValue(new Twig_Tests_EnvironmentTest_Runtime()));
|
478 |
|
479 |
+
$loader = new ArrayLoader([
|
480 |
'func_array' => '{{ from_runtime_array("foo") }}',
|
481 |
'func_array_default' => '{{ from_runtime_array() }}',
|
482 |
'func_array_named_args' => '{{ from_runtime_array(name="foo") }}',
|
485 |
'func_string_named_args' => '{{ from_runtime_string(name="foo") }}',
|
486 |
]);
|
487 |
|
488 |
+
$twig = new Environment($loader);
|
489 |
$twig->addExtension(new Twig_Tests_EnvironmentTest_ExtensionWithoutRuntime());
|
490 |
$twig->addRuntimeLoader($runtimeLoader);
|
491 |
|
498 |
}
|
499 |
|
500 |
/**
|
501 |
+
* @expectedException \Twig\Error\RuntimeError
|
502 |
* @expectedExceptionMessage Circular reference detected for Twig template "base.html.twig", path: base.html.twig -> base.html.twig in "base.html.twig" at line 1
|
503 |
*/
|
504 |
public function testFailLoadTemplateOnCircularReference()
|
505 |
{
|
506 |
+
$twig = new Environment(new ArrayLoader([
|
507 |
'base.html.twig' => '{% extends "base.html.twig" %}',
|
508 |
]));
|
509 |
|
511 |
}
|
512 |
|
513 |
/**
|
514 |
+
* @expectedException \Twig\Error\RuntimeError
|
515 |
* @expectedExceptionMessage Circular reference detected for Twig template "base1.html.twig", path: base1.html.twig -> base2.html.twig -> base1.html.twig in "base1.html.twig" at line 1
|
516 |
*/
|
517 |
public function testFailLoadTemplateOnComplexCircularReference()
|
518 |
{
|
519 |
+
$twig = new Environment(new ArrayLoader([
|
520 |
'base1.html.twig' => '{% extends "base2.html.twig" %}',
|
521 |
'base2.html.twig' => '{% extends "base1.html.twig" %}',
|
522 |
]));
|
528 |
{
|
529 |
// to be removed in 2.0
|
530 |
$loader = $this->getMockBuilder('Twig_EnvironmentTestLoaderInterface')->getMock();
|
531 |
+
//$loader = $this->getMockBuilder(['\Twig\Loader\LoaderInterface', '\Twig\Loader\SourceContextLoaderInterface'])->getMock();
|
532 |
$loader->expects($this->any())
|
533 |
->method('getSourceContext')
|
534 |
->with($templateName)
|
535 |
+
->will($this->returnValue(new Source($templateContent, $templateName)));
|
536 |
$loader->expects($this->any())
|
537 |
->method('getCacheKey')
|
538 |
->with($templateName)
|
542 |
}
|
543 |
}
|
544 |
|
545 |
+
class Twig_Tests_EnvironmentTest_Extension_WithGlobals extends AbstractExtension
|
546 |
{
|
547 |
public function getGlobals()
|
548 |
{
|
552 |
}
|
553 |
}
|
554 |
|
555 |
+
class Twig_Tests_EnvironmentTest_Extension extends AbstractExtension implements GlobalsInterface
|
556 |
{
|
557 |
public function getTokenParsers()
|
558 |
{
|
571 |
public function getFilters()
|
572 |
{
|
573 |
return [
|
574 |
+
new TwigFilter('foo_filter', 'foo_filter'),
|
575 |
];
|
576 |
}
|
577 |
|
578 |
public function getTests()
|
579 |
{
|
580 |
return [
|
581 |
+
new TwigTest('foo_test', 'foo_test'),
|
582 |
];
|
583 |
}
|
584 |
|
585 |
public function getFunctions()
|
586 |
{
|
587 |
return [
|
588 |
+
new TwigFunction('foo_function', 'foo_function'),
|
589 |
];
|
590 |
}
|
591 |
|
606 |
}
|
607 |
class_alias('Twig_Tests_EnvironmentTest_Extension', 'Twig\Tests\EnvironmentTest\Extension', false);
|
608 |
|
609 |
+
class Twig_Tests_EnvironmentTest_Extension_WithDeprecatedName extends AbstractExtension
|
610 |
{
|
611 |
public function getName()
|
612 |
{
|
614 |
}
|
615 |
}
|
616 |
|
617 |
+
class Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName extends AbstractExtension
|
618 |
{
|
619 |
private $name;
|
620 |
|
629 |
}
|
630 |
}
|
631 |
|
632 |
+
class Twig_Tests_EnvironmentTest_TokenParser extends AbstractTokenParser
|
633 |
{
|
634 |
+
public function parse(Token $token)
|
635 |
{
|
636 |
}
|
637 |
|
641 |
}
|
642 |
}
|
643 |
|
644 |
+
class Twig_Tests_EnvironmentTest_NodeVisitor implements NodeVisitorInterface
|
645 |
{
|
646 |
+
public function enterNode(Twig_NodeInterface $node, Environment $env)
|
647 |
{
|
648 |
return $node;
|
649 |
}
|
650 |
|
651 |
+
public function leaveNode(Twig_NodeInterface $node, Environment $env)
|
652 |
{
|
653 |
return $node;
|
654 |
}
|
659 |
}
|
660 |
}
|
661 |
|
662 |
+
class Twig_Tests_EnvironmentTest_ExtensionWithDeprecationInitRuntime extends AbstractExtension
|
663 |
{
|
664 |
+
public function initRuntime(Environment $env)
|
665 |
{
|
666 |
}
|
667 |
}
|
668 |
|
669 |
+
class Twig_Tests_EnvironmentTest_ExtensionWithoutDeprecationInitRuntime extends AbstractExtension implements InitRuntimeInterface
|
670 |
{
|
671 |
+
public function initRuntime(Environment $env)
|
672 |
{
|
673 |
}
|
674 |
}
|
675 |
|
676 |
+
class Twig_Tests_EnvironmentTest_ExtensionWithoutRuntime extends AbstractExtension
|
677 |
{
|
678 |
public function getFunctions()
|
679 |
{
|
680 |
return [
|
681 |
+
new TwigFunction('from_runtime_array', ['Twig_Tests_EnvironmentTest_Runtime', 'fromRuntime']),
|
682 |
+
new TwigFunction('from_runtime_string', 'Twig_Tests_EnvironmentTest_Runtime::fromRuntime'),
|
683 |
];
|
684 |
}
|
685 |
|
698 |
}
|
699 |
|
700 |
// to be removed in 2.0
|
701 |
+
interface Twig_EnvironmentTestLoaderInterface extends LoaderInterface, Twig_SourceContextLoaderInterface
|
702 |
{
|
703 |
}
|
vendor/twig/twig/test/Twig/Tests/ErrorTest.php
CHANGED
@@ -9,27 +9,34 @@
|
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
class Twig_Tests_ErrorTest extends \PHPUnit\Framework\TestCase
|
13 |
{
|
14 |
public function testErrorWithObjectFilename()
|
15 |
{
|
16 |
-
$error = new
|
17 |
-
$error->setSourceContext(new
|
18 |
|
19 |
$this->assertContains('test'.DIRECTORY_SEPARATOR.'Twig'.DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR.'ErrorTest.php', $error->getMessage());
|
20 |
}
|
21 |
|
22 |
public function testErrorWithArrayFilename()
|
23 |
{
|
24 |
-
$error = new
|
25 |
-
$error->setSourceContext(new
|
26 |
|
27 |
$this->assertEquals('foo in {"foo":"bar"}', $error->getMessage());
|
28 |
}
|
29 |
|
30 |
public function testTwigExceptionGuessWithMissingVarAndArrayLoader()
|
31 |
{
|
32 |
-
$loader = new
|
33 |
'base.html' => '{% block content %}{% endblock %}',
|
34 |
'index.html' => <<<EOHTML
|
35 |
{% extends 'base.html' %}
|
@@ -41,14 +48,14 @@ class Twig_Tests_ErrorTest extends \PHPUnit\Framework\TestCase
|
|
41 |
{% endblock %}
|
42 |
EOHTML
|
43 |
]);
|
44 |
-
$twig = new
|
45 |
|
46 |
$template = $twig->loadTemplate('index.html');
|
47 |
try {
|
48 |
$template->render([]);
|
49 |
|
50 |
$this->fail();
|
51 |
-
} catch (
|
52 |
$this->assertEquals('Variable "foo" does not exist in "index
|
9 |
* file that was distributed with this source code.
|
10 |
*/
|
11 |
|
12 |
+
use Twig\Environment;
|
13 |
+
use Twig\Error\Error;
|
14 |
+
use Twig\Error\RuntimeError;
|
15 |
+
use Twig\Loader\ArrayLoader;
|
16 |
+
use Twig\Loader\FilesystemLoader;
|
17 |
+
use Twig\Source;
|
18 |
+
|
19 |
class Twig_Tests_ErrorTest extends \PHPUnit\Framework\TestCase
|
20 |
{
|
21 |
public function testErrorWithObjectFilename()
|
22 |
{
|
23 |
+
$error = new Error('foo');
|
24 |
+
$error->setSourceContext(new Source('', new \SplFileInfo(__FILE__)));
|
25 |
|
26 |
$this->assertContains('test'.DIRECTORY_SEPARATOR.'Twig'.DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR.'ErrorTest.php', $error->getMessage());
|
27 |
}
|
28 |
|
29 |
public function testErrorWithArrayFilename()
|
30 |
{
|
31 |
+
$error = new Error('foo');
|
32 |
+
$error->setSourceContext(new Source('', ['foo' => 'bar']));
|
33 |
|
34 |
$this->assertEquals('foo in {"foo":"bar"}', $error->getMessage());
|
35 |
}
|
36 |
|
37 |
public function testTwigExceptionGuessWithMissingVarAndArrayLoader()
|
38 |
{
|
39 |
+
$loader = new ArrayLoader([
|
40 |
'base.html' => '{% block content %}{% endblock %}',
|
41 |
'index.html' => <<<EOHTML
|
42 |
{% extends 'base.html' %}
|
48 |
{% endblock %}
|
49 |
EOHTML
|
50 |
]);
|
51 |
+
$twig = new Environment($loader, ['strict_variables' => true, 'debug' => true, 'cache' => false]);
|
52 |
|
53 |
$template = $twig->loadTemplate('index.html');
|
54 |
try {
|
55 |
$template->render([]);
|
56 |
|
57 |
$this->fail();
|
58 |
+
} catch (RuntimeError $e) {
|
59 |
$this->assertEquals('Variable "foo" does not exist in "index
|