From 80213088225cf4b029e8e891ecda61701cc91eee Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 15 Feb 2020 05:41:38 +0100 Subject: [PATCH] Update Twig from 1.35.0 to 1.42.4 (PHP 5.5 is now required!) This fixes some errors on PHP 7.4 and contains even more fixes Also bumped PHP version to 5.5 as Twig requires it. --- common.php | 2 +- install/index.php | 10 +- system/functions.php | 5 +- system/libs/Twig/BaseNodeVisitor.php | 54 - .../libs/Twig/{ => Cache}/CacheInterface.php | 6 +- .../{Filesystem.php => FilesystemCache.php} | 28 +- .../Twig/Cache/{Null.php => NullCache.php} | 6 +- system/libs/Twig/Compiler.php | 52 +- system/libs/Twig/Environment.php | 548 +++--- system/libs/Twig/{ => Error}/Error.php | 90 +- system/libs/Twig/Error/Loader.php | 40 - system/libs/Twig/Error/LoaderError.php | 23 + .../Error/{Runtime.php => RuntimeError.php} | 6 +- .../Error/{Syntax.php => SyntaxError.php} | 12 +- system/libs/Twig/ExpressionParser.php | 419 ++-- .../AbstractExtension.php} | 31 +- system/libs/Twig/Extension/Core.php | 1612 --------------- system/libs/Twig/Extension/CoreExtension.php | 1728 +++++++++++++++++ .../{Debug.php => DebugExtension.php} | 39 +- .../{Escaper.php => EscaperExtension.php} | 30 +- .../{ => Extension}/ExtensionInterface.php | 33 +- .../libs/Twig/Extension/GlobalsInterface.php | 8 +- .../Twig/Extension/InitRuntimeInterface.php | 8 +- .../{Optimizer.php => OptimizerExtension.php} | 10 +- .../{Profiler.php => ProfilerExtension.php} | 24 +- .../Extension/RuntimeExtensionInterface.php | 19 + .../{Sandbox.php => SandboxExtension.php} | 20 +- .../{Staging.php => StagingExtension.php} | 27 +- system/libs/Twig/Extension/StringLoader.php | 47 - .../Twig/Extension/StringLoaderExtension.php | 54 + .../Twig/FileExtensionEscapingStrategy.php | 8 +- system/libs/Twig/Lexer.php | 280 ++- .../Loader/{Array.php => ArrayLoader.php} | 25 +- .../Loader/{Chain.php => ChainLoader.php} | 77 +- .../{ => Loader}/ExistsLoaderInterface.php | 6 +- .../{Filesystem.php => FilesystemLoader.php} | 117 +- .../Twig/{ => Loader}/LoaderInterface.php | 16 +- .../SourceContextLoaderInterface.php | 13 +- system/libs/Twig/Markup.php | 8 +- .../{AutoEscape.php => AutoEscapeNode.php} | 14 +- .../Twig/Node/{Block.php => BlockNode.php} | 16 +- ...ckReference.php => BlockReferenceNode.php} | 12 +- .../libs/Twig/Node/{Body.php => BodyNode.php} | 6 +- ...heckSecurity.php => CheckSecurityNode.php} | 33 +- system/libs/Twig/Node/CheckToStringNode.php | 42 + system/libs/Twig/Node/DeprecatedNode.php | 55 + system/libs/Twig/Node/{Do.php => DoNode.php} | 15 +- .../Twig/Node/{Embed.php => EmbedNode.php} | 16 +- .../AbstractExpression.php} | 8 +- .../{Array.php => ArrayExpression.php} | 31 +- .../Expression/ArrowFunctionExpression.php | 64 + ...ssignName.php => AssignNameExpression.php} | 10 +- .../{Binary.php => Binary/AbstractBinary.php} | 18 +- .../Binary/{Add.php => AddBinary.php} | 11 +- .../Binary/{And.php => AndBinary.php} | 11 +- .../{BitwiseAnd.php => BitwiseAndBinary.php} | 11 +- .../{BitwiseOr.php => BitwiseOrBinary.php} | 11 +- .../{BitwiseXor.php => BitwiseXorBinary.php} | 11 +- .../Binary/{Concat.php => ConcatBinary.php} | 11 +- .../Binary/{Div.php => DivBinary.php} | 11 +- .../{EndsWith.php => EndsWithBinary.php} | 13 +- .../Binary/{Equal.php => EqualBinary.php} | 11 +- .../{FloorDiv.php => FloorDivBinary.php} | 13 +- .../Binary/{Greater.php => GreaterBinary.php} | 11 +- .../Node/Expression/Binary/GreaterEqual.php | 19 - .../Expression/Binary/GreaterEqualBinary.php | 24 + .../Binary/{In.php => InBinary.php} | 13 +- .../Binary/{Less.php => LessBinary.php} | 11 +- .../Twig/Node/Expression/Binary/LessEqual.php | 19 - .../Expression/Binary/LessEqualBinary.php | 24 + .../Binary/{Matches.php => MatchesBinary.php} | 13 +- .../Binary/{Mod.php => ModBinary.php} | 11 +- .../Binary/{Mul.php => MulBinary.php} | 11 +- .../{NotEqual.php => NotEqualBinary.php} | 11 +- .../Binary/{NotIn.php => NotInBinary.php} | 13 +- .../Binary/{Or.php => OrBinary.php} | 11 +- .../Binary/{Power.php => PowerBinary.php} | 15 +- .../Binary/{Range.php => RangeBinary.php} | 13 +- .../{StartsWith.php => StartsWithBinary.php} | 13 +- .../Binary/{Sub.php => SubBinary.php} | 11 +- ...rence.php => BlockReferenceExpression.php} | 25 +- .../{Call.php => CallExpression.php} | 128 +- ...ditional.php => ConditionalExpression.php} | 15 +- .../{Constant.php => ConstantExpression.php} | 13 +- .../Twig/Node/Expression/Filter/Default.php | 45 - .../Node/Expression/Filter/DefaultFilter.php | 54 + .../{Filter.php => FilterExpression.php} | 20 +- .../{Function.php => FunctionExpression.php} | 20 +- .../{GetAttr.php => GetAttrExpression.php} | 24 +- .../libs/Twig/Node/Expression/InlinePrint.php | 35 + ...ethodCall.php => MethodCallExpression.php} | 21 +- .../{Name.php => NameExpression.php} | 35 +- .../Twig/Node/Expression/NullCoalesce.php | 48 - .../Expression/NullCoalesceExpression.php | 62 + .../{Parent.php => ParentExpression.php} | 12 +- .../{TempName.php => TempNameExpression.php} | 13 +- .../Test/{Constant.php => ConstantTest.php} | 19 +- .../Twig/Node/Expression/Test/Defined.php | 61 - .../Twig/Node/Expression/Test/DefinedTest.php | 71 + .../{Divisibleby.php => DivisiblebyTest.php} | 13 +- .../Test/{Even.php => EvenTest.php} | 13 +- .../Test/{Null.php => NullTest.php} | 13 +- .../Expression/Test/{Odd.php => OddTest.php} | 13 +- .../Test/{Sameas.php => SameasTest.php} | 11 +- .../{Test.php => TestExpression.php} | 25 +- system/libs/Twig/Node/Expression/Unary.php | 29 - .../Node/Expression/Unary/AbstractUnary.php | 35 + .../Unary/{Neg.php => NegUnary.php} | 11 +- .../Unary/{Not.php => NotUnary.php} | 11 +- .../Unary/{Pos.php => PosUnary.php} | 11 +- .../Twig/Node/{Flush.php => FlushNode.php} | 12 +- .../Node/{ForLoop.php => ForLoopNode.php} | 12 +- .../libs/Twig/Node/{For.php => ForNode.php} | 28 +- system/libs/Twig/Node/{If.php => IfNode.php} | 18 +- .../Twig/Node/{Import.php => ImportNode.php} | 20 +- system/libs/Twig/Node/Include.php | 90 - system/libs/Twig/Node/IncludeNode.php | 108 ++ .../Twig/Node/{Macro.php => MacroNode.php} | 45 +- .../Twig/Node/{Module.php => ModuleNode.php} | 201 +- system/libs/Twig/{ => Node}/Node.php | 78 +- .../Twig/{ => Node}/NodeCaptureInterface.php | 6 +- .../Twig/{ => Node}/NodeOutputInterface.php | 6 +- .../Twig/Node/{Print.php => PrintNode.php} | 15 +- .../Node/{Sandbox.php => SandboxNode.php} | 21 +- system/libs/Twig/Node/SandboxedPrint.php | 51 - system/libs/Twig/Node/SandboxedPrintNode.php | 69 + .../libs/Twig/Node/{Set.php => SetNode.php} | 39 +- .../Node/{SetTemp.php => SetTempNode.php} | 12 +- system/libs/Twig/Node/Spaceless.php | 37 - system/libs/Twig/Node/SpacelessNode.php | 47 + .../libs/Twig/Node/{Text.php => TextNode.php} | 12 +- .../libs/Twig/Node/{With.php => WithNode.php} | 30 +- system/libs/Twig/NodeTraverser.php | 39 +- .../Twig/NodeVisitor/AbstractNodeVisitor.php | 59 + system/libs/Twig/NodeVisitor/Escaper.php | 154 -- .../Twig/NodeVisitor/EscaperNodeVisitor.php | 209 ++ .../Twig/NodeVisitor/NodeVisitorInterface.php | 50 + ...Optimizer.php => OptimizerNodeVisitor.php} | 110 +- ...alysis.php => SafeAnalysisNodeVisitor.php} | 80 +- system/libs/Twig/NodeVisitor/Sandbox.php | 77 - .../Twig/NodeVisitor/SandboxNodeVisitor.php | 137 ++ system/libs/Twig/NodeVisitorInterface.php | 45 - system/libs/Twig/Parser.php | 165 +- .../Dumper/{Base.php => BaseDumper.php} | 21 +- .../{Blackfire.php => BlackfireDumper.php} | 22 +- .../Dumper/{Html.php => HtmlDumper.php} | 20 +- .../Dumper/{Text.php => TextDumper.php} | 14 +- ...{EnterProfile.php => EnterProfileNode.php} | 15 +- ...{LeaveProfile.php => LeaveProfileNode.php} | 13 +- .../Twig/Profiler/NodeVisitor/Profiler.php | 67 - .../NodeVisitor/ProfilerNodeVisitor.php | 80 + system/libs/Twig/Profiler/Profile.php | 48 +- .../ContainerRuntimeLoader.php | 6 +- .../FactoryRuntimeLoader.php | 8 +- .../RuntimeLoaderInterface.php | 6 +- system/libs/Twig/Sandbox/SecurityError.php | 8 +- .../Sandbox/SecurityNotAllowedFilterError.php | 8 +- .../SecurityNotAllowedFunctionError.php | 8 +- .../Sandbox/SecurityNotAllowedMethodError.php | 8 +- .../SecurityNotAllowedPropertyError.php | 8 +- .../Sandbox/SecurityNotAllowedTagError.php | 8 +- system/libs/Twig/Sandbox/SecurityPolicy.php | 42 +- .../Twig/Sandbox/SecurityPolicyInterface.php | 8 +- system/libs/Twig/Source.php | 6 +- system/libs/Twig/Template.php | 237 ++- system/libs/Twig/TemplateWrapper.php | 60 +- system/libs/Twig/Test/IntegrationTestCase.php | 94 +- system/libs/Twig/Test/NodeTestCase.php | 30 +- system/libs/Twig/Token.php | 24 +- .../AbstractTokenParser.php} | 15 +- .../Twig/TokenParser/ApplyTokenParser.php | 58 + system/libs/Twig/TokenParser/AutoEscape.php | 83 - .../TokenParser/AutoEscapeTokenParser.php | 88 + system/libs/Twig/TokenParser/Block.php | 73 - .../Twig/TokenParser/BlockTokenParser.php | 80 + .../TokenParser/DeprecatedTokenParser.php | 44 + .../TokenParser/{Do.php => DoTokenParser.php} | 15 +- system/libs/Twig/TokenParser/Embed.php | 67 - .../Twig/TokenParser/EmbedTokenParser.php | 74 + system/libs/Twig/TokenParser/Extends.php | 46 - .../Twig/TokenParser/ExtendsTokenParser.php | 54 + system/libs/Twig/TokenParser/Filter.php | 53 - .../Twig/TokenParser/FilterTokenParser.php | 59 + system/libs/Twig/TokenParser/Flush.php | 34 - .../Twig/TokenParser/FlushTokenParser.php | 39 + system/libs/Twig/TokenParser/For.php | 127 -- .../libs/Twig/TokenParser/ForTokenParser.php | 136 ++ system/libs/Twig/TokenParser/From.php | 66 - .../libs/Twig/TokenParser/FromTokenParser.php | 72 + system/libs/Twig/TokenParser/If.php | 86 - .../libs/Twig/TokenParser/IfTokenParser.php | 91 + system/libs/Twig/TokenParser/Import.php | 41 - .../Twig/TokenParser/ImportTokenParser.php | 45 + .../{Include.php => IncludeTokenParser.php} | 27 +- system/libs/Twig/TokenParser/Macro.php | 60 - .../Twig/TokenParser/MacroTokenParser.php | 68 + system/libs/Twig/TokenParser/Sandbox.php | 61 - .../Twig/TokenParser/SandboxTokenParser.php | 67 + system/libs/Twig/TokenParser/Set.php | 75 - .../libs/Twig/TokenParser/SetTokenParser.php | 74 + system/libs/Twig/TokenParser/Spaceless.php | 51 - .../Twig/TokenParser/SpacelessTokenParser.php | 53 + .../TokenParserInterface.php | 24 +- system/libs/Twig/TokenParser/Use.php | 70 - .../libs/Twig/TokenParser/UseTokenParser.php | 75 + system/libs/Twig/TokenParser/With.php | 52 - .../libs/Twig/TokenParser/WithTokenParser.php | 57 + system/libs/Twig/TokenStream.php | 41 +- system/libs/Twig/Twig/Autoloader.php | 52 + system/libs/Twig/Twig/BaseNodeVisitor.php | 11 + system/libs/Twig/Twig/Cache/Filesystem.php | 11 + system/libs/Twig/Twig/Cache/Null.php | 11 + system/libs/Twig/Twig/CacheInterface.php | 11 + system/libs/Twig/Twig/Compiler.php | 11 + .../Twig/{ => Twig}/CompilerInterface.php | 0 .../libs/Twig/Twig/ContainerRuntimeLoader.php | 11 + system/libs/Twig/Twig/Environment.php | 11 + system/libs/Twig/Twig/Error.php | 11 + system/libs/Twig/Twig/Error/Loader.php | 11 + system/libs/Twig/Twig/Error/Runtime.php | 11 + system/libs/Twig/Twig/Error/Syntax.php | 11 + .../libs/Twig/Twig/ExistsLoaderInterface.php | 11 + system/libs/Twig/Twig/ExpressionParser.php | 11 + system/libs/Twig/Twig/Extension.php | 11 + system/libs/Twig/Twig/Extension/Core.php | 11 + system/libs/Twig/Twig/Extension/Debug.php | 11 + system/libs/Twig/Twig/Extension/Escaper.php | 11 + .../Twig/Twig/Extension/GlobalsInterface.php | 11 + .../Twig/Extension/InitRuntimeInterface.php | 11 + system/libs/Twig/Twig/Extension/Optimizer.php | 11 + system/libs/Twig/Twig/Extension/Profiler.php | 11 + system/libs/Twig/Twig/Extension/Sandbox.php | 11 + system/libs/Twig/Twig/Extension/Staging.php | 11 + .../libs/Twig/Twig/Extension/StringLoader.php | 11 + system/libs/Twig/Twig/ExtensionInterface.php | 11 + .../libs/Twig/Twig/FactoryRuntimeLoader.php | 11 + .../Twig/FileExtensionEscapingStrategy.php | 11 + system/libs/Twig/{ => Twig}/Filter.php | 18 +- .../libs/Twig/{ => Twig}/Filter/Function.php | 6 +- system/libs/Twig/{ => Twig}/Filter/Method.php | 12 +- system/libs/Twig/{ => Twig}/Filter/Node.php | 6 +- .../{ => Twig}/FilterCallableInterface.php | 2 +- .../libs/Twig/{ => Twig}/FilterInterface.php | 6 +- system/libs/Twig/{ => Twig}/Function.php | 20 +- .../Twig/{ => Twig}/Function/Function.php | 6 +- .../libs/Twig/{ => Twig}/Function/Method.php | 12 +- system/libs/Twig/{ => Twig}/Function/Node.php | 6 +- .../{ => Twig}/FunctionCallableInterface.php | 2 +- .../Twig/{ => Twig}/FunctionInterface.php | 6 +- system/libs/Twig/Twig/Lexer.php | 11 + .../libs/Twig/{ => Twig}/LexerInterface.php | 12 +- system/libs/Twig/Twig/Loader/Array.php | 11 + system/libs/Twig/Twig/Loader/Chain.php | 11 + system/libs/Twig/Twig/Loader/Filesystem.php | 11 + system/libs/Twig/{ => Twig}/Loader/String.php | 13 +- system/libs/Twig/Twig/LoaderInterface.php | 11 + system/libs/Twig/Twig/Markup.php | 11 + system/libs/Twig/Twig/Node.php | 11 + system/libs/Twig/Twig/Node/AutoEscape.php | 11 + system/libs/Twig/Twig/Node/Block.php | 11 + system/libs/Twig/Twig/Node/BlockReference.php | 11 + system/libs/Twig/Twig/Node/Body.php | 11 + system/libs/Twig/Twig/Node/CheckSecurity.php | 11 + system/libs/Twig/Twig/Node/Deprecated.php | 11 + system/libs/Twig/Twig/Node/Do.php | 11 + system/libs/Twig/Twig/Node/Embed.php | 11 + system/libs/Twig/Twig/Node/Expression.php | 11 + .../libs/Twig/Twig/Node/Expression/Array.php | 11 + .../Twig/Twig/Node/Expression/AssignName.php | 11 + .../libs/Twig/Twig/Node/Expression/Binary.php | 11 + .../Twig/Twig/Node/Expression/Binary/Add.php | 11 + .../Twig/Twig/Node/Expression/Binary/And.php | 11 + .../Node/Expression/Binary/BitwiseAnd.php | 11 + .../Twig/Node/Expression/Binary/BitwiseOr.php | 11 + .../Node/Expression/Binary/BitwiseXor.php | 11 + .../Twig/Node/Expression/Binary/Concat.php | 11 + .../Twig/Twig/Node/Expression/Binary/Div.php | 11 + .../Twig/Node/Expression/Binary/EndsWith.php | 11 + .../Twig/Node/Expression/Binary/Equal.php | 11 + .../Twig/Node/Expression/Binary/FloorDiv.php | 11 + .../Twig/Node/Expression/Binary/Greater.php | 11 + .../Node/Expression/Binary/GreaterEqual.php | 11 + .../Twig/Twig/Node/Expression/Binary/In.php | 11 + .../Twig/Twig/Node/Expression/Binary/Less.php | 11 + .../Twig/Node/Expression/Binary/LessEqual.php | 11 + .../Twig/Node/Expression/Binary/Matches.php | 11 + .../Twig/Twig/Node/Expression/Binary/Mod.php | 11 + .../Twig/Twig/Node/Expression/Binary/Mul.php | 11 + .../Twig/Node/Expression/Binary/NotEqual.php | 11 + .../Twig/Node/Expression/Binary/NotIn.php | 11 + .../Twig/Twig/Node/Expression/Binary/Or.php | 11 + .../Twig/Node/Expression/Binary/Power.php | 11 + .../Twig/Node/Expression/Binary/Range.php | 11 + .../Node/Expression/Binary/StartsWith.php | 11 + .../Twig/Twig/Node/Expression/Binary/Sub.php | 11 + .../Twig/Node/Expression/BlockReference.php | 11 + .../libs/Twig/Twig/Node/Expression/Call.php | 11 + .../Twig/Twig/Node/Expression/Conditional.php | 11 + .../Twig/Twig/Node/Expression/Constant.php | 11 + .../Node/Expression/ExtensionReference.php | 9 +- .../libs/Twig/Twig/Node/Expression/Filter.php | 11 + .../Twig/Node/Expression/Filter/Default.php | 11 + .../Twig/Twig/Node/Expression/Function.php | 11 + .../Twig/Twig/Node/Expression/GetAttr.php | 11 + .../Twig/Twig/Node/Expression/MethodCall.php | 11 + .../libs/Twig/Twig/Node/Expression/Name.php | 11 + .../Twig/Node/Expression/NullCoalesce.php | 11 + .../libs/Twig/Twig/Node/Expression/Parent.php | 11 + .../Twig/Twig/Node/Expression/TempName.php | 11 + .../libs/Twig/Twig/Node/Expression/Test.php | 11 + .../Twig/Node/Expression/Test/Constant.php | 11 + .../Twig/Node/Expression/Test/Defined.php | 11 + .../Twig/Node/Expression/Test/Divisibleby.php | 11 + .../Twig/Twig/Node/Expression/Test/Even.php | 11 + .../Twig/Twig/Node/Expression/Test/Null.php | 11 + .../Twig/Twig/Node/Expression/Test/Odd.php | 11 + .../Twig/Twig/Node/Expression/Test/Sameas.php | 11 + .../libs/Twig/Twig/Node/Expression/Unary.php | 11 + .../Twig/Twig/Node/Expression/Unary/Neg.php | 11 + .../Twig/Twig/Node/Expression/Unary/Not.php | 11 + .../Twig/Twig/Node/Expression/Unary/Pos.php | 11 + system/libs/Twig/Twig/Node/Flush.php | 11 + system/libs/Twig/Twig/Node/For.php | 11 + system/libs/Twig/Twig/Node/ForLoop.php | 11 + system/libs/Twig/Twig/Node/If.php | 11 + system/libs/Twig/Twig/Node/Import.php | 11 + system/libs/Twig/Twig/Node/Include.php | 11 + system/libs/Twig/Twig/Node/Macro.php | 11 + system/libs/Twig/Twig/Node/Module.php | 11 + system/libs/Twig/Twig/Node/Print.php | 11 + system/libs/Twig/Twig/Node/Sandbox.php | 11 + system/libs/Twig/Twig/Node/SandboxedPrint.php | 11 + system/libs/Twig/Twig/Node/Set.php | 11 + system/libs/Twig/Twig/Node/SetTemp.php | 11 + system/libs/Twig/Twig/Node/Spaceless.php | 11 + system/libs/Twig/Twig/Node/Text.php | 11 + system/libs/Twig/Twig/Node/With.php | 11 + .../libs/Twig/Twig/NodeCaptureInterface.php | 11 + system/libs/Twig/{ => Twig}/NodeInterface.php | 6 +- system/libs/Twig/Twig/NodeOutputInterface.php | 11 + system/libs/Twig/Twig/NodeTraverser.php | 11 + system/libs/Twig/Twig/NodeVisitor/Escaper.php | 11 + .../libs/Twig/Twig/NodeVisitor/Optimizer.php | 11 + .../Twig/Twig/NodeVisitor/SafeAnalysis.php | 11 + system/libs/Twig/Twig/NodeVisitor/Sandbox.php | 11 + .../libs/Twig/Twig/NodeVisitorInterface.php | 11 + system/libs/Twig/Twig/Parser.php | 11 + .../libs/Twig/{ => Twig}/ParserInterface.php | 10 +- .../libs/Twig/Twig/Profiler/Dumper/Base.php | 11 + .../Twig/Twig/Profiler/Dumper/Blackfire.php | 11 + .../libs/Twig/Twig/Profiler/Dumper/Html.php | 11 + .../libs/Twig/Twig/Profiler/Dumper/Text.php | 11 + .../Twig/Twig/Profiler/Node/EnterProfile.php | 11 + .../Twig/Twig/Profiler/Node/LeaveProfile.php | 11 + .../Twig/Profiler/NodeVisitor/Profiler.php | 11 + system/libs/Twig/Twig/Profiler/Profile.php | 11 + .../libs/Twig/Twig/RuntimeLoaderInterface.php | 11 + .../libs/Twig/Twig/Sandbox/SecurityError.php | 11 + .../Sandbox/SecurityNotAllowedFilterError.php | 11 + .../SecurityNotAllowedFunctionError.php | 11 + .../Sandbox/SecurityNotAllowedMethodError.php | 11 + .../SecurityNotAllowedPropertyError.php | 11 + .../Sandbox/SecurityNotAllowedTagError.php | 11 + .../libs/Twig/Twig/Sandbox/SecurityPolicy.php | 11 + .../Twig/Sandbox/SecurityPolicyInterface.php | 11 + system/libs/Twig/Twig/SimpleFilter.php | 11 + system/libs/Twig/Twig/SimpleFunction.php | 11 + system/libs/Twig/Twig/SimpleTest.php | 11 + system/libs/Twig/Twig/Source.php | 11 + .../Twig/SourceContextLoaderInterface.php | 11 + system/libs/Twig/Twig/Template.php | 11 + .../Twig/{ => Twig}/TemplateInterface.php | 6 +- system/libs/Twig/Twig/TemplateWrapper.php | 11 + system/libs/Twig/{ => Twig}/Test.php | 10 +- system/libs/Twig/{ => Twig}/Test/Function.php | 4 +- .../Twig/Twig/Test/IntegrationTestCase.php | 11 + system/libs/Twig/{ => Twig}/Test/Method.php | 10 +- system/libs/Twig/{ => Twig}/Test/Node.php | 2 +- system/libs/Twig/Twig/Test/NodeTestCase.php | 11 + .../Twig/{ => Twig}/TestCallableInterface.php | 0 system/libs/Twig/{ => Twig}/TestInterface.php | 0 system/libs/Twig/Twig/Token.php | 11 + system/libs/Twig/Twig/TokenParser.php | 11 + .../libs/Twig/Twig/TokenParser/AutoEscape.php | 11 + system/libs/Twig/Twig/TokenParser/Block.php | 11 + .../libs/Twig/Twig/TokenParser/Deprecated.php | 11 + system/libs/Twig/Twig/TokenParser/Do.php | 11 + system/libs/Twig/Twig/TokenParser/Embed.php | 11 + system/libs/Twig/Twig/TokenParser/Extends.php | 11 + system/libs/Twig/Twig/TokenParser/Filter.php | 11 + system/libs/Twig/Twig/TokenParser/Flush.php | 11 + system/libs/Twig/Twig/TokenParser/For.php | 11 + system/libs/Twig/Twig/TokenParser/From.php | 11 + system/libs/Twig/Twig/TokenParser/If.php | 11 + system/libs/Twig/Twig/TokenParser/Import.php | 11 + system/libs/Twig/Twig/TokenParser/Include.php | 11 + system/libs/Twig/Twig/TokenParser/Macro.php | 11 + system/libs/Twig/Twig/TokenParser/Sandbox.php | 11 + system/libs/Twig/Twig/TokenParser/Set.php | 11 + .../libs/Twig/Twig/TokenParser/Spaceless.php | 11 + system/libs/Twig/Twig/TokenParser/Use.php | 11 + system/libs/Twig/Twig/TokenParser/With.php | 11 + .../Twig/{ => Twig}/TokenParserBroker.php | 30 +- .../{ => Twig}/TokenParserBrokerInterface.php | 8 +- .../libs/Twig/Twig/TokenParserInterface.php | 11 + system/libs/Twig/Twig/TokenStream.php | 11 + .../Twig/Twig/Util/DeprecationCollector.php | 11 + .../Twig/Twig/Util/TemplateDirIterator.php | 11 + .../Twig/{SimpleFilter.php => TwigFilter.php} | 25 +- .../{SimpleFunction.php => TwigFunction.php} | 27 +- .../Twig/{SimpleTest.php => TwigTest.php} | 26 +- .../libs/Twig/Util/DeprecationCollector.php | 34 +- system/libs/Twig/Util/TemplateDirIterator.php | 6 +- system/twig.php | 27 +- 414 files changed, 9276 insertions(+), 5531 deletions(-) delete mode 100755 system/libs/Twig/BaseNodeVisitor.php rename system/libs/Twig/{ => Cache}/CacheInterface.php (92%) rename system/libs/Twig/Cache/{Filesystem.php => FilesystemCache.php} (66%) rename system/libs/Twig/Cache/{Null.php => NullCache.php} (82%) rename system/libs/Twig/{ => Error}/Error.php (75%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/Error/Loader.php create mode 100644 system/libs/Twig/Error/LoaderError.php rename system/libs/Twig/Error/{Runtime.php => RuntimeError.php} (74%) mode change 100755 => 100644 rename system/libs/Twig/Error/{Syntax.php => SyntaxError.php} (78%) mode change 100755 => 100644 rename system/libs/Twig/{Extension.php => Extension/AbstractExtension.php} (62%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/Extension/Core.php create mode 100644 system/libs/Twig/Extension/CoreExtension.php rename system/libs/Twig/Extension/{Debug.php => DebugExtension.php} (58%) mode change 100755 => 100644 rename system/libs/Twig/Extension/{Escaper.php => EscaperExtension.php} (76%) mode change 100755 => 100644 rename system/libs/Twig/{ => Extension}/ExtensionInterface.php (70%) mode change 100755 => 100644 rename system/libs/Twig/Extension/{Optimizer.php => OptimizerExtension.php} (64%) mode change 100755 => 100644 rename system/libs/Twig/Extension/{Profiler.php => ProfilerExtension.php} (54%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Extension/RuntimeExtensionInterface.php rename system/libs/Twig/Extension/{Sandbox.php => SandboxExtension.php} (74%) mode change 100755 => 100644 rename system/libs/Twig/Extension/{Staging.php => StagingExtension.php} (78%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/Extension/StringLoader.php create mode 100644 system/libs/Twig/Extension/StringLoaderExtension.php rename system/libs/Twig/Loader/{Array.php => ArrayLoader.php} (71%) mode change 100755 => 100644 rename system/libs/Twig/Loader/{Chain.php => ChainLoader.php} (50%) mode change 100755 => 100644 rename system/libs/Twig/{ => Loader}/ExistsLoaderInterface.php (82%) mode change 100755 => 100644 rename system/libs/Twig/Loader/{Filesystem.php => FilesystemLoader.php} (65%) mode change 100755 => 100644 rename system/libs/Twig/{ => Loader}/LoaderInterface.php (78%) mode change 100755 => 100644 rename system/libs/Twig/{ => Loader}/SourceContextLoaderInterface.php (67%) rename system/libs/Twig/Node/{AutoEscape.php => AutoEscapeNode.php} (59%) mode change 100755 => 100644 rename system/libs/Twig/Node/{Block.php => BlockNode.php} (60%) mode change 100755 => 100644 rename system/libs/Twig/Node/{BlockReference.php => BlockReferenceNode.php} (66%) mode change 100755 => 100644 rename system/libs/Twig/Node/{Body.php => BodyNode.php} (74%) mode change 100755 => 100644 rename system/libs/Twig/Node/{CheckSecurity.php => CheckSecurityNode.php} (60%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Node/CheckToStringNode.php create mode 100644 system/libs/Twig/Node/DeprecatedNode.php rename system/libs/Twig/Node/{Do.php => DoNode.php} (57%) mode change 100755 => 100644 rename system/libs/Twig/Node/{Embed.php => EmbedNode.php} (64%) mode change 100755 => 100644 rename system/libs/Twig/Node/{Expression.php => Expression/AbstractExpression.php} (66%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/{Array.php => ArrayExpression.php} (64%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Node/Expression/ArrowFunctionExpression.php rename system/libs/Twig/Node/Expression/{AssignName.php => AssignNameExpression.php} (60%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/{Binary.php => Binary/AbstractBinary.php} (50%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{Add.php => AddBinary.php} (53%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{And.php => AndBinary.php} (53%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{BitwiseAnd.php => BitwiseAndBinary.php} (51%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{BitwiseOr.php => BitwiseOrBinary.php} (51%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{BitwiseXor.php => BitwiseXorBinary.php} (51%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{Concat.php => ConcatBinary.php} (52%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{Div.php => DivBinary.php} (53%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{EndsWith.php => EndsWithBinary.php} (69%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{Equal.php => EqualBinary.php} (51%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{FloorDiv.php => FloorDivBinary.php} (55%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{Greater.php => GreaterBinary.php} (50%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/Node/Expression/Binary/GreaterEqual.php create mode 100644 system/libs/Twig/Node/Expression/Binary/GreaterEqualBinary.php rename system/libs/Twig/Node/Expression/Binary/{In.php => InBinary.php} (62%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{Less.php => LessBinary.php} (51%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/Node/Expression/Binary/LessEqual.php create mode 100644 system/libs/Twig/Node/Expression/Binary/LessEqualBinary.php rename system/libs/Twig/Node/Expression/Binary/{Matches.php => MatchesBinary.php} (61%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{Mod.php => ModBinary.php} (53%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{Mul.php => MulBinary.php} (53%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{NotEqual.php => NotEqualBinary.php} (50%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{NotIn.php => NotInBinary.php} (62%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{Or.php => OrBinary.php} (54%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{Power.php => PowerBinary.php} (61%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{Range.php => RangeBinary.php} (61%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{StartsWith.php => StartsWithBinary.php} (69%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Binary/{Sub.php => SubBinary.php} (53%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/{BlockReference.php => BlockReferenceExpression.php} (73%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/{Call.php => CallExpression.php} (63%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/{Conditional.php => ConditionalExpression.php} (52%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/{Constant.php => ConstantExpression.php} (53%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/Node/Expression/Filter/Default.php create mode 100644 system/libs/Twig/Node/Expression/Filter/DefaultFilter.php rename system/libs/Twig/Node/Expression/{Filter.php => FilterExpression.php} (58%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/{Function.php => FunctionExpression.php} (64%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/{GetAttr.php => GetAttrExpression.php} (68%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Node/Expression/InlinePrint.php rename system/libs/Twig/Node/Expression/{MethodCall.php => MethodCallExpression.php} (59%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/{Name.php => NameExpression.php} (73%) mode change 100755 => 100644 delete mode 100644 system/libs/Twig/Node/Expression/NullCoalesce.php create mode 100644 system/libs/Twig/Node/Expression/NullCoalesceExpression.php rename system/libs/Twig/Node/Expression/{Parent.php => ParentExpression.php} (73%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/{TempName.php => TempNameExpression.php} (57%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Test/{Constant.php => ConstantTest.php} (66%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/Node/Expression/Test/Defined.php create mode 100644 system/libs/Twig/Node/Expression/Test/DefinedTest.php rename system/libs/Twig/Node/Expression/Test/{Divisibleby.php => DivisiblebyTest.php} (67%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Test/{Even.php => EvenTest.php} (64%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Test/{Null.php => NullTest.php} (63%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Test/{Odd.php => OddTest.php} (64%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Test/{Sameas.php => SameasTest.php} (66%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/{Test.php => TestExpression.php} (51%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/Node/Expression/Unary.php create mode 100644 system/libs/Twig/Node/Expression/Unary/AbstractUnary.php rename system/libs/Twig/Node/Expression/Unary/{Neg.php => NegUnary.php} (53%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Unary/{Not.php => NotUnary.php} (53%) mode change 100755 => 100644 rename system/libs/Twig/Node/Expression/Unary/{Pos.php => PosUnary.php} (53%) mode change 100755 => 100644 rename system/libs/Twig/Node/{Flush.php => FlushNode.php} (67%) mode change 100755 => 100644 rename system/libs/Twig/Node/{ForLoop.php => ForLoopNode.php} (81%) mode change 100755 => 100644 rename system/libs/Twig/Node/{For.php => ForNode.php} (75%) mode change 100755 => 100644 rename system/libs/Twig/Node/{If.php => IfNode.php} (73%) mode change 100755 => 100644 rename system/libs/Twig/Node/{Import.php => ImportNode.php} (58%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/Node/Include.php create mode 100644 system/libs/Twig/Node/IncludeNode.php rename system/libs/Twig/Node/{Macro.php => MacroNode.php} (63%) mode change 100755 => 100644 rename system/libs/Twig/Node/{Module.php => ModuleNode.php} (64%) mode change 100755 => 100644 rename system/libs/Twig/{ => Node}/Node.php (71%) mode change 100755 => 100644 rename system/libs/Twig/{ => Node}/NodeCaptureInterface.php (72%) rename system/libs/Twig/{ => Node}/NodeOutputInterface.php (71%) mode change 100755 => 100644 rename system/libs/Twig/Node/{Print.php => PrintNode.php} (57%) mode change 100755 => 100644 rename system/libs/Twig/Node/{Sandbox.php => SandboxNode.php} (51%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/Node/SandboxedPrint.php create mode 100644 system/libs/Twig/Node/SandboxedPrintNode.php rename system/libs/Twig/Node/{Set.php => SetNode.php} (63%) mode change 100755 => 100644 rename system/libs/Twig/Node/{SetTemp.php => SetTempNode.php} (74%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/Node/Spaceless.php create mode 100644 system/libs/Twig/Node/SpacelessNode.php rename system/libs/Twig/Node/{Text.php => TextNode.php} (67%) mode change 100755 => 100644 rename system/libs/Twig/Node/{With.php => WithNode.php} (52%) create mode 100644 system/libs/Twig/NodeVisitor/AbstractNodeVisitor.php delete mode 100755 system/libs/Twig/NodeVisitor/Escaper.php create mode 100644 system/libs/Twig/NodeVisitor/EscaperNodeVisitor.php create mode 100644 system/libs/Twig/NodeVisitor/NodeVisitorInterface.php rename system/libs/Twig/NodeVisitor/{Optimizer.php => OptimizerNodeVisitor.php} (57%) mode change 100755 => 100644 rename system/libs/Twig/NodeVisitor/{SafeAnalysis.php => SafeAnalysisNodeVisitor.php} (57%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/NodeVisitor/Sandbox.php create mode 100644 system/libs/Twig/NodeVisitor/SandboxNodeVisitor.php delete mode 100755 system/libs/Twig/NodeVisitorInterface.php rename system/libs/Twig/Profiler/Dumper/{Base.php => BaseDumper.php} (65%) rename system/libs/Twig/Profiler/Dumper/{Blackfire.php => BlackfireDumper.php} (77%) mode change 100755 => 100644 rename system/libs/Twig/Profiler/Dumper/{Html.php => HtmlDumper.php} (68%) mode change 100755 => 100644 rename system/libs/Twig/Profiler/Dumper/{Text.php => TextDumper.php} (60%) mode change 100755 => 100644 rename system/libs/Twig/Profiler/Node/{EnterProfile.php => EnterProfileNode.php} (58%) mode change 100755 => 100644 rename system/libs/Twig/Profiler/Node/{LeaveProfile.php => LeaveProfileNode.php} (64%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/Profiler/NodeVisitor/Profiler.php create mode 100644 system/libs/Twig/Profiler/NodeVisitor/ProfilerNodeVisitor.php rename system/libs/Twig/{ => RuntimeLoader}/ContainerRuntimeLoader.php (81%) rename system/libs/Twig/{ => RuntimeLoader}/FactoryRuntimeLoader.php (75%) rename system/libs/Twig/{ => RuntimeLoader}/RuntimeLoaderInterface.php (81%) rename system/libs/Twig/{TokenParser.php => TokenParser/AbstractTokenParser.php} (56%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/TokenParser/ApplyTokenParser.php delete mode 100755 system/libs/Twig/TokenParser/AutoEscape.php create mode 100644 system/libs/Twig/TokenParser/AutoEscapeTokenParser.php delete mode 100755 system/libs/Twig/TokenParser/Block.php create mode 100644 system/libs/Twig/TokenParser/BlockTokenParser.php create mode 100644 system/libs/Twig/TokenParser/DeprecatedTokenParser.php rename system/libs/Twig/TokenParser/{Do.php => DoTokenParser.php} (54%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/TokenParser/Embed.php create mode 100644 system/libs/Twig/TokenParser/EmbedTokenParser.php delete mode 100755 system/libs/Twig/TokenParser/Extends.php create mode 100644 system/libs/Twig/TokenParser/ExtendsTokenParser.php delete mode 100755 system/libs/Twig/TokenParser/Filter.php create mode 100644 system/libs/Twig/TokenParser/FilterTokenParser.php delete mode 100755 system/libs/Twig/TokenParser/Flush.php create mode 100644 system/libs/Twig/TokenParser/FlushTokenParser.php delete mode 100755 system/libs/Twig/TokenParser/For.php create mode 100644 system/libs/Twig/TokenParser/ForTokenParser.php delete mode 100755 system/libs/Twig/TokenParser/From.php create mode 100644 system/libs/Twig/TokenParser/FromTokenParser.php delete mode 100755 system/libs/Twig/TokenParser/If.php create mode 100644 system/libs/Twig/TokenParser/IfTokenParser.php delete mode 100755 system/libs/Twig/TokenParser/Import.php create mode 100644 system/libs/Twig/TokenParser/ImportTokenParser.php rename system/libs/Twig/TokenParser/{Include.php => IncludeTokenParser.php} (57%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/TokenParser/Macro.php create mode 100644 system/libs/Twig/TokenParser/MacroTokenParser.php delete mode 100755 system/libs/Twig/TokenParser/Sandbox.php create mode 100644 system/libs/Twig/TokenParser/SandboxTokenParser.php delete mode 100755 system/libs/Twig/TokenParser/Set.php create mode 100644 system/libs/Twig/TokenParser/SetTokenParser.php delete mode 100755 system/libs/Twig/TokenParser/Spaceless.php create mode 100644 system/libs/Twig/TokenParser/SpacelessTokenParser.php rename system/libs/Twig/{ => TokenParser}/TokenParserInterface.php (53%) mode change 100755 => 100644 delete mode 100755 system/libs/Twig/TokenParser/Use.php create mode 100644 system/libs/Twig/TokenParser/UseTokenParser.php delete mode 100644 system/libs/Twig/TokenParser/With.php create mode 100644 system/libs/Twig/TokenParser/WithTokenParser.php create mode 100644 system/libs/Twig/Twig/Autoloader.php create mode 100644 system/libs/Twig/Twig/BaseNodeVisitor.php create mode 100644 system/libs/Twig/Twig/Cache/Filesystem.php create mode 100644 system/libs/Twig/Twig/Cache/Null.php create mode 100644 system/libs/Twig/Twig/CacheInterface.php create mode 100644 system/libs/Twig/Twig/Compiler.php rename system/libs/Twig/{ => Twig}/CompilerInterface.php (100%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Twig/ContainerRuntimeLoader.php create mode 100644 system/libs/Twig/Twig/Environment.php create mode 100644 system/libs/Twig/Twig/Error.php create mode 100644 system/libs/Twig/Twig/Error/Loader.php create mode 100644 system/libs/Twig/Twig/Error/Runtime.php create mode 100644 system/libs/Twig/Twig/Error/Syntax.php create mode 100644 system/libs/Twig/Twig/ExistsLoaderInterface.php create mode 100644 system/libs/Twig/Twig/ExpressionParser.php create mode 100644 system/libs/Twig/Twig/Extension.php create mode 100644 system/libs/Twig/Twig/Extension/Core.php create mode 100644 system/libs/Twig/Twig/Extension/Debug.php create mode 100644 system/libs/Twig/Twig/Extension/Escaper.php create mode 100644 system/libs/Twig/Twig/Extension/GlobalsInterface.php create mode 100644 system/libs/Twig/Twig/Extension/InitRuntimeInterface.php create mode 100644 system/libs/Twig/Twig/Extension/Optimizer.php create mode 100644 system/libs/Twig/Twig/Extension/Profiler.php create mode 100644 system/libs/Twig/Twig/Extension/Sandbox.php create mode 100644 system/libs/Twig/Twig/Extension/Staging.php create mode 100644 system/libs/Twig/Twig/Extension/StringLoader.php create mode 100644 system/libs/Twig/Twig/ExtensionInterface.php create mode 100644 system/libs/Twig/Twig/FactoryRuntimeLoader.php create mode 100644 system/libs/Twig/Twig/FileExtensionEscapingStrategy.php rename system/libs/Twig/{ => Twig}/Filter.php (79%) mode change 100755 => 100644 rename system/libs/Twig/{ => Twig}/Filter/Function.php (77%) mode change 100755 => 100644 rename system/libs/Twig/{ => Twig}/Filter/Method.php (61%) mode change 100755 => 100644 rename system/libs/Twig/{ => Twig}/Filter/Node.php (78%) mode change 100755 => 100644 rename system/libs/Twig/{ => Twig}/FilterCallableInterface.php (92%) mode change 100755 => 100644 rename system/libs/Twig/{ => Twig}/FilterInterface.php (88%) mode change 100755 => 100644 rename system/libs/Twig/{ => Twig}/Function.php (74%) mode change 100755 => 100644 rename system/libs/Twig/{ => Twig}/Function/Function.php (78%) mode change 100755 => 100644 rename system/libs/Twig/{ => Twig}/Function/Method.php (62%) mode change 100755 => 100644 rename system/libs/Twig/{ => Twig}/Function/Node.php (77%) mode change 100755 => 100644 rename system/libs/Twig/{ => Twig}/FunctionCallableInterface.php (92%) mode change 100755 => 100644 rename system/libs/Twig/{ => Twig}/FunctionInterface.php (87%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Twig/Lexer.php rename system/libs/Twig/{ => Twig}/LexerInterface.php (64%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Twig/Loader/Array.php create mode 100644 system/libs/Twig/Twig/Loader/Chain.php create mode 100644 system/libs/Twig/Twig/Loader/Filesystem.php rename system/libs/Twig/{ => Twig}/Loader/String.php (70%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Twig/LoaderInterface.php create mode 100644 system/libs/Twig/Twig/Markup.php create mode 100644 system/libs/Twig/Twig/Node.php create mode 100644 system/libs/Twig/Twig/Node/AutoEscape.php create mode 100644 system/libs/Twig/Twig/Node/Block.php create mode 100644 system/libs/Twig/Twig/Node/BlockReference.php create mode 100644 system/libs/Twig/Twig/Node/Body.php create mode 100644 system/libs/Twig/Twig/Node/CheckSecurity.php create mode 100644 system/libs/Twig/Twig/Node/Deprecated.php create mode 100644 system/libs/Twig/Twig/Node/Do.php create mode 100644 system/libs/Twig/Twig/Node/Embed.php create mode 100644 system/libs/Twig/Twig/Node/Expression.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Array.php create mode 100644 system/libs/Twig/Twig/Node/Expression/AssignName.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/Add.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/And.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/BitwiseAnd.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/BitwiseOr.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/BitwiseXor.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/Concat.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/Div.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/EndsWith.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/Equal.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/FloorDiv.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/Greater.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/GreaterEqual.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/In.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/Less.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/LessEqual.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/Matches.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/Mod.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/Mul.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/NotEqual.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/NotIn.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/Or.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/Power.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/Range.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/StartsWith.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Binary/Sub.php create mode 100644 system/libs/Twig/Twig/Node/Expression/BlockReference.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Call.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Conditional.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Constant.php rename system/libs/Twig/{ => Twig}/Node/Expression/ExtensionReference.php (73%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Twig/Node/Expression/Filter.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Filter/Default.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Function.php create mode 100644 system/libs/Twig/Twig/Node/Expression/GetAttr.php create mode 100644 system/libs/Twig/Twig/Node/Expression/MethodCall.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Name.php create mode 100644 system/libs/Twig/Twig/Node/Expression/NullCoalesce.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Parent.php create mode 100644 system/libs/Twig/Twig/Node/Expression/TempName.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Test.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Test/Constant.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Test/Defined.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Test/Divisibleby.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Test/Even.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Test/Null.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Test/Odd.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Test/Sameas.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Unary.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Unary/Neg.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Unary/Not.php create mode 100644 system/libs/Twig/Twig/Node/Expression/Unary/Pos.php create mode 100644 system/libs/Twig/Twig/Node/Flush.php create mode 100644 system/libs/Twig/Twig/Node/For.php create mode 100644 system/libs/Twig/Twig/Node/ForLoop.php create mode 100644 system/libs/Twig/Twig/Node/If.php create mode 100644 system/libs/Twig/Twig/Node/Import.php create mode 100644 system/libs/Twig/Twig/Node/Include.php create mode 100644 system/libs/Twig/Twig/Node/Macro.php create mode 100644 system/libs/Twig/Twig/Node/Module.php create mode 100644 system/libs/Twig/Twig/Node/Print.php create mode 100644 system/libs/Twig/Twig/Node/Sandbox.php create mode 100644 system/libs/Twig/Twig/Node/SandboxedPrint.php create mode 100644 system/libs/Twig/Twig/Node/Set.php create mode 100644 system/libs/Twig/Twig/Node/SetTemp.php create mode 100644 system/libs/Twig/Twig/Node/Spaceless.php create mode 100644 system/libs/Twig/Twig/Node/Text.php create mode 100644 system/libs/Twig/Twig/Node/With.php create mode 100644 system/libs/Twig/Twig/NodeCaptureInterface.php rename system/libs/Twig/{ => Twig}/NodeInterface.php (79%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Twig/NodeOutputInterface.php create mode 100644 system/libs/Twig/Twig/NodeTraverser.php create mode 100644 system/libs/Twig/Twig/NodeVisitor/Escaper.php create mode 100644 system/libs/Twig/Twig/NodeVisitor/Optimizer.php create mode 100644 system/libs/Twig/Twig/NodeVisitor/SafeAnalysis.php create mode 100644 system/libs/Twig/Twig/NodeVisitor/Sandbox.php create mode 100644 system/libs/Twig/Twig/NodeVisitorInterface.php create mode 100644 system/libs/Twig/Twig/Parser.php rename system/libs/Twig/{ => Twig}/ParserInterface.php (66%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Twig/Profiler/Dumper/Base.php create mode 100644 system/libs/Twig/Twig/Profiler/Dumper/Blackfire.php create mode 100644 system/libs/Twig/Twig/Profiler/Dumper/Html.php create mode 100644 system/libs/Twig/Twig/Profiler/Dumper/Text.php create mode 100644 system/libs/Twig/Twig/Profiler/Node/EnterProfile.php create mode 100644 system/libs/Twig/Twig/Profiler/Node/LeaveProfile.php create mode 100644 system/libs/Twig/Twig/Profiler/NodeVisitor/Profiler.php create mode 100644 system/libs/Twig/Twig/Profiler/Profile.php create mode 100644 system/libs/Twig/Twig/RuntimeLoaderInterface.php create mode 100644 system/libs/Twig/Twig/Sandbox/SecurityError.php create mode 100644 system/libs/Twig/Twig/Sandbox/SecurityNotAllowedFilterError.php create mode 100644 system/libs/Twig/Twig/Sandbox/SecurityNotAllowedFunctionError.php create mode 100644 system/libs/Twig/Twig/Sandbox/SecurityNotAllowedMethodError.php create mode 100644 system/libs/Twig/Twig/Sandbox/SecurityNotAllowedPropertyError.php create mode 100644 system/libs/Twig/Twig/Sandbox/SecurityNotAllowedTagError.php create mode 100644 system/libs/Twig/Twig/Sandbox/SecurityPolicy.php create mode 100644 system/libs/Twig/Twig/Sandbox/SecurityPolicyInterface.php create mode 100644 system/libs/Twig/Twig/SimpleFilter.php create mode 100644 system/libs/Twig/Twig/SimpleFunction.php create mode 100644 system/libs/Twig/Twig/SimpleTest.php create mode 100644 system/libs/Twig/Twig/Source.php create mode 100644 system/libs/Twig/Twig/SourceContextLoaderInterface.php create mode 100644 system/libs/Twig/Twig/Template.php rename system/libs/Twig/{ => Twig}/TemplateInterface.php (90%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Twig/TemplateWrapper.php rename system/libs/Twig/{ => Twig}/Test.php (72%) mode change 100755 => 100644 rename system/libs/Twig/{ => Twig}/Test/Function.php (81%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Twig/Test/IntegrationTestCase.php rename system/libs/Twig/{ => Twig}/Test/Method.php (63%) mode change 100755 => 100644 rename system/libs/Twig/{ => Twig}/Test/Node.php (91%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Twig/Test/NodeTestCase.php rename system/libs/Twig/{ => Twig}/TestCallableInterface.php (100%) mode change 100755 => 100644 rename system/libs/Twig/{ => Twig}/TestInterface.php (100%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Twig/Token.php create mode 100644 system/libs/Twig/Twig/TokenParser.php create mode 100644 system/libs/Twig/Twig/TokenParser/AutoEscape.php create mode 100644 system/libs/Twig/Twig/TokenParser/Block.php create mode 100644 system/libs/Twig/Twig/TokenParser/Deprecated.php create mode 100644 system/libs/Twig/Twig/TokenParser/Do.php create mode 100644 system/libs/Twig/Twig/TokenParser/Embed.php create mode 100644 system/libs/Twig/Twig/TokenParser/Extends.php create mode 100644 system/libs/Twig/Twig/TokenParser/Filter.php create mode 100644 system/libs/Twig/Twig/TokenParser/Flush.php create mode 100644 system/libs/Twig/Twig/TokenParser/For.php create mode 100644 system/libs/Twig/Twig/TokenParser/From.php create mode 100644 system/libs/Twig/Twig/TokenParser/If.php create mode 100644 system/libs/Twig/Twig/TokenParser/Import.php create mode 100644 system/libs/Twig/Twig/TokenParser/Include.php create mode 100644 system/libs/Twig/Twig/TokenParser/Macro.php create mode 100644 system/libs/Twig/Twig/TokenParser/Sandbox.php create mode 100644 system/libs/Twig/Twig/TokenParser/Set.php create mode 100644 system/libs/Twig/Twig/TokenParser/Spaceless.php create mode 100644 system/libs/Twig/Twig/TokenParser/Use.php create mode 100644 system/libs/Twig/Twig/TokenParser/With.php rename system/libs/Twig/{ => Twig}/TokenParserBroker.php (68%) mode change 100755 => 100644 rename system/libs/Twig/{ => Twig}/TokenParserBrokerInterface.php (73%) mode change 100755 => 100644 create mode 100644 system/libs/Twig/Twig/TokenParserInterface.php create mode 100644 system/libs/Twig/Twig/TokenStream.php create mode 100644 system/libs/Twig/Twig/Util/DeprecationCollector.php create mode 100644 system/libs/Twig/Twig/Util/TemplateDirIterator.php rename system/libs/Twig/{SimpleFilter.php => TwigFilter.php} (80%) mode change 100755 => 100644 rename system/libs/Twig/{SimpleFunction.php => TwigFunction.php} (77%) mode change 100755 => 100644 rename system/libs/Twig/{SimpleTest.php => TwigTest.php} (74%) mode change 100755 => 100644 diff --git a/common.php b/common.php index d9c79b8d..33a3125e 100644 --- a/common.php +++ b/common.php @@ -23,7 +23,7 @@ * @copyright 2019 MyAAC * @link https://my-aac.org */ -if (version_compare(phpversion(), '5.3.3', '<')) die('PHP version 5.3.3 or higher is required.'); +if (version_compare(phpversion(), '5.5', '<')) die('PHP version 5.5 or higher is required.'); session_start(); define('MYAAC', true); diff --git a/install/index.php b/install/index.php index 7cebc9b0..255d89e2 100644 --- a/install/index.php +++ b/install/index.php @@ -1,4 +1,8 @@ CACHE . 'twig/', 'auto_reload' => true diff --git a/system/functions.php b/system/functions.php index a246559b..87efbff6 100644 --- a/system/functions.php +++ b/system/functions.php @@ -7,6 +7,9 @@ * @copyright 2019 MyAAC * @link https://my-aac.org */ + +use Twig\Loader\ArrayLoader as Twig_ArrayLoader; + defined('MYAAC') or die('Direct access not allowed!'); function message($message, $type, $return) @@ -1190,7 +1193,7 @@ function getCustomPage($page, &$success) else { $oldLoader = $twig->getLoader(); - $twig_loader_array = new Twig_Loader_Array(array( + $twig_loader_array = new Twig_ArrayLoader(array( 'content.html' => $query['body'] )); diff --git a/system/libs/Twig/BaseNodeVisitor.php b/system/libs/Twig/BaseNodeVisitor.php deleted file mode 100755 index d8ef02fb..00000000 --- a/system/libs/Twig/BaseNodeVisitor.php +++ /dev/null @@ -1,54 +0,0 @@ - - */ -abstract class Twig_BaseNodeVisitor implements Twig_NodeVisitorInterface -{ - final public function enterNode(Twig_NodeInterface $node, Twig_Environment $env) - { - if (!$node instanceof Twig_Node) { - throw new LogicException('Twig_BaseNodeVisitor only supports Twig_Node instances.'); - } - - return $this->doEnterNode($node, $env); - } - - final public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env) - { - if (!$node instanceof Twig_Node) { - throw new LogicException('Twig_BaseNodeVisitor only supports Twig_Node instances.'); - } - - return $this->doLeaveNode($node, $env); - } - - /** - * Called before child nodes are visited. - * - * @return Twig_Node The modified node - */ - abstract protected function doEnterNode(Twig_Node $node, Twig_Environment $env); - - /** - * Called after child nodes are visited. - * - * @return Twig_Node|false The modified node or false if the node must be removed - */ - abstract protected function doLeaveNode(Twig_Node $node, Twig_Environment $env); -} - -class_alias('Twig_BaseNodeVisitor', 'Twig\NodeVisitor\AbstractNodeVisitor', false); -class_exists('Twig_Environment'); -class_exists('Twig_Node'); diff --git a/system/libs/Twig/CacheInterface.php b/system/libs/Twig/Cache/CacheInterface.php similarity index 92% rename from system/libs/Twig/CacheInterface.php rename to system/libs/Twig/Cache/CacheInterface.php index 776808bf..1c8bb1ec 100644 --- a/system/libs/Twig/CacheInterface.php +++ b/system/libs/Twig/Cache/CacheInterface.php @@ -9,6 +9,8 @@ * file that was distributed with this source code. */ +namespace Twig\Cache; + /** * Interface implemented by cache classes. * @@ -18,7 +20,7 @@ * * @author Andrew Tch */ -interface Twig_CacheInterface +interface CacheInterface { /** * Generates a cache key for the given template class name. @@ -55,4 +57,4 @@ interface Twig_CacheInterface public function getTimestamp($key); } -class_alias('Twig_CacheInterface', 'Twig\Cache\CacheInterface', false); +class_alias('Twig\Cache\CacheInterface', 'Twig_CacheInterface'); diff --git a/system/libs/Twig/Cache/Filesystem.php b/system/libs/Twig/Cache/FilesystemCache.php similarity index 66% rename from system/libs/Twig/Cache/Filesystem.php rename to system/libs/Twig/Cache/FilesystemCache.php index 65976282..b7c1e438 100644 --- a/system/libs/Twig/Cache/Filesystem.php +++ b/system/libs/Twig/Cache/FilesystemCache.php @@ -9,12 +9,14 @@ * file that was distributed with this source code. */ +namespace Twig\Cache; + /** * Implements a cache on the filesystem. * * @author Andrew Tch */ -class Twig_Cache_Filesystem implements Twig_CacheInterface +class FilesystemCache implements CacheInterface { const FORCE_BYTECODE_INVALIDATION = 1; @@ -22,8 +24,8 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface private $options; /** - * @param $directory string The root cache directory - * @param $options int A set of options + * @param string $directory The root cache directory + * @param int $options A set of options */ public function __construct($directory, $options = 0) { @@ -47,18 +49,16 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface public function write($key, $content) { - $dir = dirname($key); + $dir = \dirname($key); if (!is_dir($dir)) { if (false === @mkdir($dir, 0777, true)) { - if (PHP_VERSION_ID >= 50300) { - clearstatcache(true, $dir); - } + clearstatcache(true, $dir); if (!is_dir($dir)) { - throw new RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir)); + throw new \RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir)); } } } elseif (!is_writable($dir)) { - throw new RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir)); + throw new \RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir)); } $tmpFile = tempnam($dir, basename($key)); @@ -67,9 +67,9 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface if (self::FORCE_BYTECODE_INVALIDATION == ($this->options & self::FORCE_BYTECODE_INVALIDATION)) { // Compile cached file into bytecode cache - if (function_exists('opcache_invalidate')) { - opcache_invalidate($key, true); - } elseif (function_exists('apc_compile_file')) { + if (\function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN)) { + @opcache_invalidate($key, true); + } elseif (\function_exists('apc_compile_file')) { apc_compile_file($key); } } @@ -77,7 +77,7 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface return; } - throw new RuntimeException(sprintf('Failed to write cache file "%s".', $key)); + throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $key)); } public function getTimestamp($key) @@ -90,4 +90,4 @@ class Twig_Cache_Filesystem implements Twig_CacheInterface } } -class_alias('Twig_Cache_Filesystem', 'Twig\Cache\FilesystemCache', false); +class_alias('Twig\Cache\FilesystemCache', 'Twig_Cache_Filesystem'); diff --git a/system/libs/Twig/Cache/Null.php b/system/libs/Twig/Cache/NullCache.php similarity index 82% rename from system/libs/Twig/Cache/Null.php rename to system/libs/Twig/Cache/NullCache.php index 69d1d2f9..c1b37c12 100644 --- a/system/libs/Twig/Cache/Null.php +++ b/system/libs/Twig/Cache/NullCache.php @@ -9,6 +9,8 @@ * file that was distributed with this source code. */ +namespace Twig\Cache; + /** * Implements a no-cache strategy. * @@ -16,7 +18,7 @@ * * @author Fabien Potencier */ -class Twig_Cache_Null implements Twig_CacheInterface +class NullCache implements CacheInterface { public function generateKey($name, $className) { @@ -37,4 +39,4 @@ class Twig_Cache_Null implements Twig_CacheInterface } } -class_alias('Twig_Cache_Null', 'Twig\Cache\NullCache', false); +class_alias('Twig\Cache\NullCache', 'Twig_Cache_Null'); diff --git a/system/libs/Twig/Compiler.php b/system/libs/Twig/Compiler.php index e90bc987..e47003ae 100755 --- a/system/libs/Twig/Compiler.php +++ b/system/libs/Twig/Compiler.php @@ -10,23 +10,28 @@ * file that was distributed with this source code. */ +namespace Twig; + +use Twig\Node\ModuleNode; + /** * Compiles a node to PHP code. * * @author Fabien Potencier */ -class Twig_Compiler implements Twig_CompilerInterface +class Compiler implements \Twig_CompilerInterface { protected $lastLine; protected $source; protected $indentation; protected $env; - protected $debugInfo = array(); + protected $debugInfo = []; protected $sourceOffset; protected $sourceLine; protected $filename; + private $varNameSalt = 0; - public function __construct(Twig_Environment $env) + public function __construct(Environment $env) { $this->env = $env; } @@ -44,7 +49,7 @@ class Twig_Compiler implements Twig_CompilerInterface /** * Returns the environment instance related to this compiler. * - * @return Twig_Environment + * @return Environment */ public function getEnvironment() { @@ -64,22 +69,22 @@ class Twig_Compiler implements Twig_CompilerInterface /** * Compiles a node. * - * @param Twig_NodeInterface $node The node to compile - * @param int $indentation The current indentation + * @param int $indentation The current indentation * * @return $this */ - public function compile(Twig_NodeInterface $node, $indentation = 0) + public function compile(\Twig_NodeInterface $node, $indentation = 0) { $this->lastLine = null; $this->source = ''; - $this->debugInfo = array(); + $this->debugInfo = []; $this->sourceOffset = 0; // source code starts at 1 (as we then increment it when we encounter new lines) $this->sourceLine = 1; $this->indentation = $indentation; + $this->varNameSalt = 0; - if ($node instanceof Twig_Node_Module) { + if ($node instanceof ModuleNode) { // to be removed in 2.0 $this->filename = $node->getTemplateName(); } @@ -89,7 +94,7 @@ class Twig_Compiler implements Twig_CompilerInterface return $this; } - public function subcompile(Twig_NodeInterface $node, $raw = true) + public function subcompile(\Twig_NodeInterface $node, $raw = true) { if (false === $raw) { $this->source .= str_repeat(' ', $this->indentation * 4); @@ -121,7 +126,7 @@ class Twig_Compiler implements Twig_CompilerInterface */ public function write() { - $strings = func_get_args(); + $strings = \func_get_args(); foreach ($strings as $string) { $this->source .= str_repeat(' ', $this->indentation * 4).$string; } @@ -168,22 +173,22 @@ class Twig_Compiler implements Twig_CompilerInterface */ public function repr($value) { - if (is_int($value) || is_float($value)) { + if (\is_int($value) || \is_float($value)) { if (false !== $locale = setlocale(LC_NUMERIC, '0')) { setlocale(LC_NUMERIC, 'C'); } - $this->raw($value); + $this->raw(var_export($value, true)); if (false !== $locale) { setlocale(LC_NUMERIC, $locale); } } elseif (null === $value) { $this->raw('null'); - } elseif (is_bool($value)) { + } elseif (\is_bool($value)) { $this->raw($value ? 'true' : 'false'); - } elseif (is_array($value)) { - $this->raw('array('); + } elseif (\is_array($value)) { + $this->raw('['); $first = true; foreach ($value as $key => $v) { if (!$first) { @@ -194,7 +199,7 @@ class Twig_Compiler implements Twig_CompilerInterface $this->raw(' => '); $this->repr($v); } - $this->raw(')'); + $this->raw(']'); } else { $this->string($value); } @@ -207,7 +212,7 @@ class Twig_Compiler implements Twig_CompilerInterface * * @return $this */ - public function addDebugInfo(Twig_NodeInterface $node) + public function addDebugInfo(\Twig_NodeInterface $node) { if ($node->getTemplateLine() != $this->lastLine) { $this->write(sprintf("// line %d\n", $node->getTemplateLine())); @@ -223,7 +228,7 @@ class Twig_Compiler implements Twig_CompilerInterface } else { $this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset); } - $this->sourceOffset = strlen($this->source); + $this->sourceOffset = \strlen($this->source); $this->debugInfo[$this->sourceLine] = $node->getTemplateLine(); $this->lastLine = $node->getTemplateLine(); @@ -260,13 +265,13 @@ class Twig_Compiler implements Twig_CompilerInterface * * @return $this * - * @throws LogicException When trying to outdent too much so the indentation would become negative + * @throws \LogicException When trying to outdent too much so the indentation would become negative */ public function outdent($step = 1) { // can't outdent by more steps than the current indentation level if ($this->indentation < $step) { - throw new LogicException('Unable to call outdent() as the indentation would become negative.'); + throw new \LogicException('Unable to call outdent() as the indentation would become negative.'); } $this->indentation -= $step; @@ -276,9 +281,8 @@ class Twig_Compiler implements Twig_CompilerInterface public function getVarName() { - return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false)); + return sprintf('__internal_%s', hash('sha256', __METHOD__.$this->varNameSalt++)); } } -class_alias('Twig_Compiler', 'Twig\Compiler', false); -class_exists('Twig_Node'); +class_alias('Twig\Compiler', 'Twig_Compiler'); diff --git a/system/libs/Twig/Environment.php b/system/libs/Twig/Environment.php index 5de2f27f..1f80f3a8 100755 --- a/system/libs/Twig/Environment.php +++ b/system/libs/Twig/Environment.php @@ -9,18 +9,43 @@ * file that was distributed with this source code. */ +namespace Twig; + +use Twig\Cache\CacheInterface; +use Twig\Cache\FilesystemCache; +use Twig\Cache\NullCache; +use Twig\Error\Error; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; +use Twig\Error\SyntaxError; +use Twig\Extension\CoreExtension; +use Twig\Extension\EscaperExtension; +use Twig\Extension\ExtensionInterface; +use Twig\Extension\GlobalsInterface; +use Twig\Extension\InitRuntimeInterface; +use Twig\Extension\OptimizerExtension; +use Twig\Extension\StagingExtension; +use Twig\Loader\ArrayLoader; +use Twig\Loader\ChainLoader; +use Twig\Loader\LoaderInterface; +use Twig\Loader\SourceContextLoaderInterface; +use Twig\Node\ModuleNode; +use Twig\NodeVisitor\NodeVisitorInterface; +use Twig\RuntimeLoader\RuntimeLoaderInterface; +use Twig\TokenParser\TokenParserInterface; + /** * Stores the Twig configuration. * * @author Fabien Potencier */ -class Twig_Environment +class Environment { - const VERSION = '1.35.0'; - const VERSION_ID = 13500; + const VERSION = '1.42.4'; + const VERSION_ID = 14204; const MAJOR_VERSION = 1; - const MINOR_VERSION = 35; - const RELEASE_VERSION = 0; + const MINOR_VERSION = 42; + const RELEASE_VERSION = 4; const EXTRA_VERSION = ''; protected $charset; @@ -46,19 +71,18 @@ class Twig_Environment protected $unaryOperators; protected $binaryOperators; protected $templateClassPrefix = '__TwigTemplate_'; - protected $functionCallbacks = array(); - protected $filterCallbacks = array(); + protected $functionCallbacks = []; + protected $filterCallbacks = []; protected $staging; private $originalCache; private $bcWriteCacheFile = false; private $bcGetCacheFilename = false; private $lastModifiedExtension = 0; - private $extensionsByClass = array(); - private $runtimeLoaders = array(); - private $runtimes = array(); + private $extensionsByClass = []; + private $runtimeLoaders = []; + private $runtimes = []; private $optionsHash; - private $loading = array(); /** * Constructor. @@ -71,10 +95,10 @@ class Twig_Environment * * charset: The charset used by the templates (default to UTF-8). * * * base_template_class: The base template class to use for generated - * templates (default to Twig_Template). + * templates (default to \Twig\Template). * * * cache: An absolute path where to store the compiled templates, - * a Twig_Cache_Interface implementation, + * a \Twig\Cache\CacheInterface implementation, * or false to disable compilation cache (default). * * * auto_reload: Whether to reload the template if the original source changed. @@ -94,28 +118,25 @@ class Twig_Environment * * optimizations: A flag that indicates which optimizations to apply * (default to -1 which means that all optimizations are enabled; * set it to 0 to disable). - * - * @param Twig_LoaderInterface $loader - * @param array $options An array of options */ - public function __construct(Twig_LoaderInterface $loader = null, $options = array()) + public function __construct(LoaderInterface $loader = null, $options = []) { if (null !== $loader) { $this->setLoader($loader); } else { - @trigger_error('Not passing a Twig_LoaderInterface as the first constructor argument of Twig_Environment is deprecated since version 1.21.', E_USER_DEPRECATED); + @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); } - $options = array_merge(array( + $options = array_merge([ 'debug' => false, 'charset' => 'UTF-8', - 'base_template_class' => 'Twig_Template', + 'base_template_class' => '\Twig\Template', 'strict_variables' => false, 'autoescape' => 'html', 'cache' => false, 'auto_reload' => null, 'optimizations' => -1, - ), $options); + ], $options); $this->debug = (bool) $options['debug']; $this->charset = strtoupper($options['charset']); @@ -124,23 +145,23 @@ class Twig_Environment $this->strictVariables = (bool) $options['strict_variables']; $this->setCache($options['cache']); - $this->addExtension(new Twig_Extension_Core()); - $this->addExtension(new Twig_Extension_Escaper($options['autoescape'])); - $this->addExtension(new Twig_Extension_Optimizer($options['optimizations'])); - $this->staging = new Twig_Extension_Staging(); + $this->addExtension(new CoreExtension()); + $this->addExtension(new EscaperExtension($options['autoescape'])); + $this->addExtension(new OptimizerExtension($options['optimizations'])); + $this->staging = new StagingExtension(); // For BC - if (is_string($this->originalCache)) { - $r = new ReflectionMethod($this, 'writeCacheFile'); - if ($r->getDeclaringClass()->getName() !== __CLASS__) { - @trigger_error('The Twig_Environment::writeCacheFile method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED); + if (\is_string($this->originalCache)) { + $r = new \ReflectionMethod($this, 'writeCacheFile'); + if (__CLASS__ !== $r->getDeclaringClass()->getName()) { + @trigger_error('The Twig\Environment::writeCacheFile method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED); $this->bcWriteCacheFile = true; } - $r = new ReflectionMethod($this, 'getCacheFilename'); - if ($r->getDeclaringClass()->getName() !== __CLASS__) { - @trigger_error('The Twig_Environment::getCacheFilename method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED); + $r = new \ReflectionMethod($this, 'getCacheFilename'); + if (__CLASS__ !== $r->getDeclaringClass()->getName()) { + @trigger_error('The Twig\Environment::getCacheFilename method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED); $this->bcGetCacheFilename = true; } @@ -255,9 +276,9 @@ class Twig_Environment * * @param bool $original Whether to return the original cache option or the real cache instance * - * @return Twig_CacheInterface|string|false A Twig_CacheInterface implementation, - * an absolute path to the compiled templates, - * or false to disable cache + * @return CacheInterface|string|false A Twig\Cache\CacheInterface implementation, + * an absolute path to the compiled templates, + * or false to disable cache */ public function getCache($original = true) { @@ -267,26 +288,26 @@ class Twig_Environment /** * Sets the current cache implementation. * - * @param Twig_CacheInterface|string|false $cache A Twig_CacheInterface implementation, - * an absolute path to the compiled templates, - * or false to disable cache + * @param CacheInterface|string|false $cache A Twig\Cache\CacheInterface implementation, + * an absolute path to the compiled templates, + * or false to disable cache */ public function setCache($cache) { - if (is_string($cache)) { + if (\is_string($cache)) { $this->originalCache = $cache; - $this->cache = new Twig_Cache_Filesystem($cache); + $this->cache = new FilesystemCache($cache); } elseif (false === $cache) { $this->originalCache = $cache; - $this->cache = new Twig_Cache_Null(); + $this->cache = new NullCache(); } elseif (null === $cache) { @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); $this->originalCache = false; - $this->cache = new Twig_Cache_Null(); - } elseif ($cache instanceof Twig_CacheInterface) { + $this->cache = new NullCache(); + } elseif ($cache instanceof CacheInterface) { $this->originalCache = $this->cache = $cache; } else { - throw new LogicException(sprintf('Cache can only be a string, false, or a Twig_CacheInterface implementation.')); + throw new \LogicException(sprintf('Cache can only be a string, false, or a \Twig\Cache\CacheInterface implementation.')); } } @@ -329,7 +350,7 @@ class Twig_Environment { $key = $this->getLoader()->getCacheKey($name).$this->optionsHash; - return $this->templateClassPrefix.hash('sha256', $key).(null === $index ? '' : '_'.$index); + return $this->templateClassPrefix.hash('sha256', $key).(null === $index ? '' : '___'.$index); } /** @@ -349,57 +370,57 @@ class Twig_Environment /** * Renders a template. * - * @param string $name The template name - * @param array $context An array of parameters to pass to the template + * @param string|TemplateWrapper $name The template name + * @param array $context An array of parameters to pass to the template * * @return string The rendered template * - * @throws Twig_Error_Loader When the template cannot be found - * @throws Twig_Error_Syntax When an error occurred during compilation - * @throws Twig_Error_Runtime When an error occurred during rendering + * @throws LoaderError When the template cannot be found + * @throws SyntaxError When an error occurred during compilation + * @throws RuntimeError When an error occurred during rendering */ - public function render($name, array $context = array()) + public function render($name, array $context = []) { - return $this->loadTemplate($name)->render($context); + return $this->load($name)->render($context); } /** * Displays a template. * - * @param string $name The template name - * @param array $context An array of parameters to pass to the template + * @param string|TemplateWrapper $name The template name + * @param array $context An array of parameters to pass to the template * - * @throws Twig_Error_Loader When the template cannot be found - * @throws Twig_Error_Syntax When an error occurred during compilation - * @throws Twig_Error_Runtime When an error occurred during rendering + * @throws LoaderError When the template cannot be found + * @throws SyntaxError When an error occurred during compilation + * @throws RuntimeError When an error occurred during rendering */ - public function display($name, array $context = array()) + public function display($name, array $context = []) { - $this->loadTemplate($name)->display($context); + $this->load($name)->display($context); } /** * Loads a template. * - * @param string|Twig_TemplateWrapper|Twig_Template $name The template name + * @param string|TemplateWrapper|\Twig\Template $name The template name * - * @throws Twig_Error_Loader When the template cannot be found - * @throws Twig_Error_Runtime When a previously generated cache is corrupted - * @throws Twig_Error_Syntax When an error occurred during compilation + * @throws LoaderError When the template cannot be found + * @throws RuntimeError When a previously generated cache is corrupted + * @throws SyntaxError When an error occurred during compilation * - * @return Twig_TemplateWrapper + * @return TemplateWrapper */ public function load($name) { - if ($name instanceof Twig_TemplateWrapper) { + if ($name instanceof TemplateWrapper) { return $name; } - if ($name instanceof Twig_Template) { - return new Twig_TemplateWrapper($this, $name); + if ($name instanceof Template) { + return new TemplateWrapper($this, $name); } - return new Twig_TemplateWrapper($this, $this->loadTemplate($name)); + return new TemplateWrapper($this, $this->loadTemplate($name)); } /** @@ -411,19 +432,27 @@ class Twig_Environment * @param string $name The template name * @param int $index The index if it is an embedded template * - * @return Twig_TemplateInterface A template instance representing the given template name + * @return \Twig_TemplateInterface A template instance representing the given template name * - * @throws Twig_Error_Loader When the template cannot be found - * @throws Twig_Error_Runtime When a previously generated cache is corrupted - * @throws Twig_Error_Syntax When an error occurred during compilation + * @throws LoaderError When the template cannot be found + * @throws RuntimeError When a previously generated cache is corrupted + * @throws SyntaxError When an error occurred during compilation * * @internal */ public function loadTemplate($name, $index = null) { - $cls = $mainCls = $this->getTemplateClass($name); + return $this->loadClass($this->getTemplateClass($name), $name, $index); + } + + /** + * @internal + */ + public function loadClass($cls, $name, $index = null) + { + $mainCls = $cls; if (null !== $index) { - $cls .= '_'.$index; + $cls .= '___'.$index; } if (isset($this->loadedTemplates[$cls])) { @@ -441,10 +470,11 @@ class Twig_Environment $this->cache->load($key); } + $source = null; if (!class_exists($cls, false)) { $loader = $this->getLoader(); - if (!$loader instanceof Twig_SourceContextLoaderInterface) { - $source = new Twig_Source($loader->getSource($name), $name); + if (!$loader instanceof SourceContextLoaderInterface) { + $source = new Source($loader->getSource($name), $name); } else { $source = $loader->getSourceContext($name); } @@ -469,7 +499,7 @@ class Twig_Environment } if (!class_exists($cls, false)) { - throw new Twig_Error_Runtime(sprintf('Failed to load Twig template "%s", index "%s": cache is corrupted.', $name, $index), -1, $source); + throw new RuntimeError(sprintf('Failed to load Twig template "%s", index "%s": cache might be corrupted.', $name, $index), -1, $source); } } @@ -477,22 +507,7 @@ class Twig_Environment $this->initRuntime(); } - if (isset($this->loading[$cls])) { - throw new Twig_Error_Runtime(sprintf('Circular reference detected for Twig template "%s", path: %s.', $name, implode(' -> ', array_merge($this->loading, array($name))))); - } - - $this->loading[$cls] = $name; - - try { - $this->loadedTemplates[$cls] = new $cls($this); - unset($this->loading[$cls]); - } catch (\Exception $e) { - unset($this->loading[$cls]); - - throw $e; - } - - return $this->loadedTemplates[$cls]; + return $this->loadedTemplates[$cls] = new $cls($this); } /** @@ -500,30 +515,36 @@ class Twig_Environment * * This method should not be used as a generic way to load templates. * - * @param string $template The template name + * @param string $template The template source + * @param string $name An optional name of the template to be used in error messages * - * @return Twig_Template A template instance representing the given template name + * @return TemplateWrapper A template instance representing the given template name * - * @throws Twig_Error_Loader When the template cannot be found - * @throws Twig_Error_Syntax When an error occurred during compilation + * @throws LoaderError When the template cannot be found + * @throws SyntaxError When an error occurred during compilation */ - public function createTemplate($template) + public function createTemplate($template, $name = null) { - $name = sprintf('__string_template__%s', hash('sha256', $template, false)); + $hash = hash('sha256', $template, false); + if (null !== $name) { + $name = sprintf('%s (string template %s)', $name, $hash); + } else { + $name = sprintf('__string_template__%s', $hash); + } - $loader = new Twig_Loader_Chain(array( - new Twig_Loader_Array(array($name => $template)), + $loader = new ChainLoader([ + new ArrayLoader([$name => $template]), $current = $this->getLoader(), - )); + ]); $this->setLoader($loader); try { - $template = $this->loadTemplate($name); - } catch (Exception $e) { + $template = new TemplateWrapper($this, $this->loadTemplate($name)); + } catch (\Exception $e) { $this->setLoader($current); throw $e; - } catch (Throwable $e) { + } catch (\Throwable $e) { $this->setLoader($current); throw $e; @@ -549,7 +570,7 @@ class Twig_Environment { if (0 === $this->lastModifiedExtension) { foreach ($this->extensions as $extension) { - $r = new ReflectionObject($extension); + $r = new \ReflectionObject($extension); if (file_exists($r->getFileName()) && ($extensionTime = filemtime($r->getFileName())) > $this->lastModifiedExtension) { $this->lastModifiedExtension = $extensionTime; } @@ -562,38 +583,40 @@ class Twig_Environment /** * Tries to load a template consecutively from an array. * - * Similar to loadTemplate() but it also accepts Twig_TemplateInterface instances and an array - * of templates where each is tried to be loaded. + * Similar to load() but it also accepts instances of \Twig\Template and + * \Twig\TemplateWrapper, and an array of templates where each is tried to be loaded. * - * @param string|Twig_Template|array $names A template or an array of templates to try consecutively + * @param string|Template|\Twig\TemplateWrapper|array $names A template or an array of templates to try consecutively * - * @return Twig_Template + * @return TemplateWrapper|Template * - * @throws Twig_Error_Loader When none of the templates can be found - * @throws Twig_Error_Syntax When an error occurred during compilation + * @throws LoaderError When none of the templates can be found + * @throws SyntaxError When an error occurred during compilation */ public function resolveTemplate($names) { - if (!is_array($names)) { - $names = array($names); + if (!\is_array($names)) { + $names = [$names]; } foreach ($names as $name) { - if ($name instanceof Twig_Template) { + if ($name instanceof Template) { + return $name; + } + if ($name instanceof TemplateWrapper) { return $name; } try { return $this->loadTemplate($name); - } catch (Twig_Error_Loader $e) { + } catch (LoaderError $e) { + if (1 === \count($names)) { + throw $e; + } } } - if (1 === count($names)) { - throw $e; - } - - throw new Twig_Error_Loader(sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names))); + throw new LoaderError(sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names))); } /** @@ -605,7 +628,7 @@ class Twig_Environment { @trigger_error(sprintf('The %s method is deprecated since version 1.18.3 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); - $this->loadedTemplates = array(); + $this->loadedTemplates = []; } /** @@ -617,8 +640,8 @@ class Twig_Environment { @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); - if (is_string($this->originalCache)) { - foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->originalCache), RecursiveIteratorIterator::LEAVES_ONLY) as $file) { + if (\is_string($this->originalCache)) { + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->originalCache), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { if ($file->isFile()) { @unlink($file->getPathname()); } @@ -629,7 +652,7 @@ class Twig_Environment /** * Gets the Lexer instance. * - * @return Twig_LexerInterface + * @return \Twig_LexerInterface * * @deprecated since 1.25 (to be removed in 2.0) */ @@ -638,13 +661,13 @@ class Twig_Environment @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED); if (null === $this->lexer) { - $this->lexer = new Twig_Lexer($this); + $this->lexer = new Lexer($this); } return $this->lexer; } - public function setLexer(Twig_LexerInterface $lexer) + public function setLexer(\Twig_LexerInterface $lexer) { $this->lexer = $lexer; } @@ -652,22 +675,22 @@ class Twig_Environment /** * Tokenizes a source code. * - * @param string|Twig_Source $source The template source code - * @param string $name The template name (deprecated) + * @param string|Source $source The template source code + * @param string $name The template name (deprecated) * - * @return Twig_TokenStream + * @return TokenStream * - * @throws Twig_Error_Syntax When the code is syntactically wrong + * @throws SyntaxError When the code is syntactically wrong */ public function tokenize($source, $name = null) { - if (!$source instanceof Twig_Source) { - @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); - $source = new Twig_Source($source, $name); + if (!$source instanceof Source) { + @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); + $source = new Source($source, $name); } if (null === $this->lexer) { - $this->lexer = new Twig_Lexer($this); + $this->lexer = new Lexer($this); } return $this->lexer->tokenize($source); @@ -676,7 +699,7 @@ class Twig_Environment /** * Gets the Parser instance. * - * @return Twig_ParserInterface + * @return \Twig_ParserInterface * * @deprecated since 1.25 (to be removed in 2.0) */ @@ -685,13 +708,13 @@ class Twig_Environment @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED); if (null === $this->parser) { - $this->parser = new Twig_Parser($this); + $this->parser = new Parser($this); } return $this->parser; } - public function setParser(Twig_ParserInterface $parser) + public function setParser(\Twig_ParserInterface $parser) { $this->parser = $parser; } @@ -699,14 +722,14 @@ class Twig_Environment /** * Converts a token stream to a node tree. * - * @return Twig_Node_Module + * @return ModuleNode * - * @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong + * @throws SyntaxError When the token stream is syntactically or semantically wrong */ - public function parse(Twig_TokenStream $stream) + public function parse(TokenStream $stream) { if (null === $this->parser) { - $this->parser = new Twig_Parser($this); + $this->parser = new Parser($this); } return $this->parser->parse($stream); @@ -715,7 +738,7 @@ class Twig_Environment /** * Gets the Compiler instance. * - * @return Twig_CompilerInterface + * @return \Twig_CompilerInterface * * @deprecated since 1.25 (to be removed in 2.0) */ @@ -724,13 +747,13 @@ class Twig_Environment @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED); if (null === $this->compiler) { - $this->compiler = new Twig_Compiler($this); + $this->compiler = new Compiler($this); } return $this->compiler; } - public function setCompiler(Twig_CompilerInterface $compiler) + public function setCompiler(\Twig_CompilerInterface $compiler) { $this->compiler = $compiler; } @@ -740,10 +763,10 @@ class Twig_Environment * * @return string The compiled PHP source code */ - public function compile(Twig_NodeInterface $node) + public function compile(\Twig_NodeInterface $node) { if (null === $this->compiler) { - $this->compiler = new Twig_Compiler($this); + $this->compiler = new Compiler($this); } return $this->compiler->compile($node)->getSource(); @@ -752,34 +775,34 @@ class Twig_Environment /** * Compiles a template source code. * - * @param string|Twig_Source $source The template source code - * @param string $name The template name (deprecated) + * @param string|Source $source The template source code + * @param string $name The template name (deprecated) * * @return string The compiled PHP source code * - * @throws Twig_Error_Syntax When there was an error during tokenizing, parsing or compiling + * @throws SyntaxError When there was an error during tokenizing, parsing or compiling */ public function compileSource($source, $name = null) { - if (!$source instanceof Twig_Source) { - @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); - $source = new Twig_Source($source, $name); + if (!$source instanceof Source) { + @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); + $source = new Source($source, $name); } try { return $this->compile($this->parse($this->tokenize($source))); - } catch (Twig_Error $e) { + } catch (Error $e) { $e->setSourceContext($source); throw $e; - } catch (Exception $e) { - throw new Twig_Error_Syntax(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $source, $e); + } catch (\Exception $e) { + throw new SyntaxError(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $source, $e); } } - public function setLoader(Twig_LoaderInterface $loader) + public function setLoader(LoaderInterface $loader) { - if (!$loader instanceof Twig_SourceContextLoaderInterface && 0 !== strpos(get_class($loader), 'Mock_')) { - @trigger_error(sprintf('Twig loader "%s" should implement Twig_SourceContextLoaderInterface since version 1.27.', get_class($loader)), E_USER_DEPRECATED); + if (!$loader instanceof SourceContextLoaderInterface && 0 !== strpos(\get_class($loader), 'Mock_')) { + @trigger_error(sprintf('Twig loader "%s" should implement Twig\Loader\SourceContextLoaderInterface since version 1.27.', \get_class($loader)), E_USER_DEPRECATED); } $this->loader = $loader; @@ -788,12 +811,12 @@ class Twig_Environment /** * Gets the Loader instance. * - * @return Twig_LoaderInterface + * @return LoaderInterface */ public function getLoader() { if (null === $this->loader) { - throw new LogicException('You must set a loader first.'); + throw new \LogicException('You must set a loader first.'); } return $this->loader; @@ -829,11 +852,12 @@ class Twig_Environment $this->runtimeInitialized = true; foreach ($this->getExtensions() as $name => $extension) { - if (!$extension instanceof Twig_Extension_InitRuntimeInterface) { - $m = new ReflectionMethod($extension, 'initRuntime'); + if (!$extension instanceof InitRuntimeInterface) { + $m = new \ReflectionMethod($extension, 'initRuntime'); - if ('Twig_Extension' !== $m->getDeclaringClass()->getName()) { - @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); + $parentClass = $m->getDeclaringClass()->getName(); + if ('Twig_Extension' !== $parentClass && 'Twig\Extension\AbstractExtension' !== $parentClass) { + @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); } } @@ -853,12 +877,12 @@ class Twig_Environment $class = ltrim($class, '\\'); if (!isset($this->extensionsByClass[$class]) && class_exists($class, false)) { // For BC/FC with namespaced aliases - $class = new ReflectionClass($class); + $class = new \ReflectionClass($class); $class = $class->name; } if (isset($this->extensions[$class])) { - if ($class !== get_class($this->extensions[$class])) { + if ($class !== \get_class($this->extensions[$class])) { @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); } @@ -871,7 +895,7 @@ class Twig_Environment /** * Adds a runtime loader. */ - public function addRuntimeLoader(Twig_RuntimeLoaderInterface $loader) + public function addRuntimeLoader(RuntimeLoaderInterface $loader) { $this->runtimeLoaders[] = $loader; } @@ -881,19 +905,19 @@ class Twig_Environment * * @param string $class The extension class name * - * @return Twig_ExtensionInterface + * @return ExtensionInterface */ public function getExtension($class) { $class = ltrim($class, '\\'); if (!isset($this->extensionsByClass[$class]) && class_exists($class, false)) { // For BC/FC with namespaced aliases - $class = new ReflectionClass($class); + $class = new \ReflectionClass($class); $class = $class->name; } if (isset($this->extensions[$class])) { - if ($class !== get_class($this->extensions[$class])) { + if ($class !== \get_class($this->extensions[$class])) { @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); } @@ -901,7 +925,7 @@ class Twig_Environment } if (!isset($this->extensionsByClass[$class])) { - throw new Twig_Error_Runtime(sprintf('The "%s" extension is not enabled.', $class)); + throw new RuntimeError(sprintf('The "%s" extension is not enabled.', $class)); } return $this->extensionsByClass[$class]; @@ -914,7 +938,7 @@ class Twig_Environment * * @return object The runtime implementation * - * @throws Twig_Error_Runtime When the template cannot be found + * @throws RuntimeError When the template cannot be found */ public function getRuntime($class) { @@ -928,16 +952,16 @@ class Twig_Environment } } - throw new Twig_Error_Runtime(sprintf('Unable to load the "%s" runtime.', $class)); + throw new RuntimeError(sprintf('Unable to load the "%s" runtime.', $class)); } - public function addExtension(Twig_ExtensionInterface $extension) + public function addExtension(ExtensionInterface $extension) { if ($this->extensionInitialized) { - throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName())); + throw new \LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName())); } - $class = get_class($extension); + $class = \get_class($extension); if ($class !== $extension->getName()) { if (isset($this->extensions[$extension->getName()])) { unset($this->extensions[$extension->getName()], $this->extensionsByClass[$class]); @@ -965,18 +989,18 @@ class Twig_Environment @trigger_error(sprintf('The %s method is deprecated since version 1.12 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); if ($this->extensionInitialized) { - throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name)); + throw new \LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name)); } $class = ltrim($name, '\\'); if (!isset($this->extensionsByClass[$class]) && class_exists($class, false)) { // For BC/FC with namespaced aliases - $class = new ReflectionClass($class); + $class = new \ReflectionClass($class); $class = $class->name; } if (isset($this->extensions[$class])) { - if ($class !== get_class($this->extensions[$class])) { + if ($class !== \get_class($this->extensions[$class])) { @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); } @@ -1002,17 +1026,17 @@ class Twig_Environment /** * Returns all registered extensions. * - * @return Twig_ExtensionInterface[] An array of extensions (keys are for internal usage only and should not be relied on) + * @return ExtensionInterface[] An array of extensions (keys are for internal usage only and should not be relied on) */ public function getExtensions() { return $this->extensions; } - public function addTokenParser(Twig_TokenParserInterface $parser) + public function addTokenParser(TokenParserInterface $parser) { if ($this->extensionInitialized) { - throw new LogicException('Unable to add a token parser as extensions have already been initialized.'); + throw new \LogicException('Unable to add a token parser as extensions have already been initialized.'); } $this->staging->addTokenParser($parser); @@ -1021,7 +1045,7 @@ class Twig_Environment /** * Gets the registered Token Parsers. * - * @return Twig_TokenParserBrokerInterface + * @return \Twig_TokenParserBrokerInterface * * @internal */ @@ -1037,17 +1061,17 @@ class Twig_Environment /** * Gets registered tags. * - * Be warned that this method cannot return tags defined by Twig_TokenParserBrokerInterface classes. + * Be warned that this method cannot return tags defined by \Twig_TokenParserBrokerInterface classes. * - * @return Twig_TokenParserInterface[] + * @return TokenParserInterface[] * * @internal */ public function getTags() { - $tags = array(); + $tags = []; foreach ($this->getTokenParsers()->getParsers() as $parser) { - if ($parser instanceof Twig_TokenParserInterface) { + if ($parser instanceof TokenParserInterface) { $tags[$parser->getTag()] = $parser; } } @@ -1055,10 +1079,10 @@ class Twig_Environment return $tags; } - public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) + public function addNodeVisitor(NodeVisitorInterface $visitor) { if ($this->extensionInitialized) { - throw new LogicException('Unable to add a node visitor as extensions have already been initialized.'); + throw new \LogicException('Unable to add a node visitor as extensions have already been initialized.'); } $this->staging->addNodeVisitor($visitor); @@ -1067,7 +1091,7 @@ class Twig_Environment /** * Gets the registered Node Visitors. * - * @return Twig_NodeVisitorInterface[] + * @return NodeVisitorInterface[] * * @internal */ @@ -1083,16 +1107,16 @@ class Twig_Environment /** * Registers a Filter. * - * @param string|Twig_SimpleFilter $name The filter name or a Twig_SimpleFilter instance - * @param Twig_FilterInterface|Twig_SimpleFilter $filter + * @param string|TwigFilter $name The filter name or a \Twig_SimpleFilter instance + * @param \Twig_FilterInterface|TwigFilter $filter */ public function addFilter($name, $filter = null) { - if (!$name instanceof Twig_SimpleFilter && !($filter instanceof Twig_SimpleFilter || $filter instanceof Twig_FilterInterface)) { - throw new LogicException('A filter must be an instance of Twig_FilterInterface or Twig_SimpleFilter.'); + if (!$name instanceof TwigFilter && !($filter instanceof TwigFilter || $filter instanceof \Twig_FilterInterface)) { + throw new \LogicException('A filter must be an instance of \Twig_FilterInterface or \Twig_SimpleFilter.'); } - if ($name instanceof Twig_SimpleFilter) { + if ($name instanceof TwigFilter) { $filter = $name; $name = $filter->getName(); } else { @@ -1100,7 +1124,7 @@ class Twig_Environment } if ($this->extensionInitialized) { - throw new LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name)); + throw new \LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name)); } $this->staging->addFilter($name, $filter); @@ -1114,7 +1138,7 @@ class Twig_Environment * * @param string $name The filter name * - * @return Twig_Filter|false A Twig_Filter instance or false if the filter does not exist + * @return \Twig_Filter|false * * @internal */ @@ -1142,7 +1166,7 @@ class Twig_Environment } foreach ($this->filterCallbacks as $callback) { - if (false !== $filter = call_user_func($callback, $name)) { + if (false !== $filter = \call_user_func($callback, $name)) { return $filter; } } @@ -1160,7 +1184,7 @@ class Twig_Environment * * Be warned that this method cannot return filters defined with registerUndefinedFilterCallback. * - * @return Twig_FilterInterface[] + * @return \Twig_FilterInterface[] * * @see registerUndefinedFilterCallback * @@ -1178,16 +1202,16 @@ class Twig_Environment /** * Registers a Test. * - * @param string|Twig_SimpleTest $name The test name or a Twig_SimpleTest instance - * @param Twig_TestInterface|Twig_SimpleTest $test A Twig_TestInterface instance or a Twig_SimpleTest instance + * @param string|TwigTest $name The test name or a \Twig_SimpleTest instance + * @param \Twig_TestInterface|TwigTest $test A \Twig_TestInterface instance or a \Twig_SimpleTest instance */ public function addTest($name, $test = null) { - if (!$name instanceof Twig_SimpleTest && !($test instanceof Twig_SimpleTest || $test instanceof Twig_TestInterface)) { - throw new LogicException('A test must be an instance of Twig_TestInterface or Twig_SimpleTest.'); + if (!$name instanceof TwigTest && !($test instanceof TwigTest || $test instanceof \Twig_TestInterface)) { + throw new \LogicException('A test must be an instance of \Twig_TestInterface or \Twig_SimpleTest.'); } - if ($name instanceof Twig_SimpleTest) { + if ($name instanceof TwigTest) { $test = $name; $name = $test->getName(); } else { @@ -1195,7 +1219,7 @@ class Twig_Environment } if ($this->extensionInitialized) { - throw new LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name)); + throw new \LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name)); } $this->staging->addTest($name, $test); @@ -1204,7 +1228,7 @@ class Twig_Environment /** * Gets the registered Tests. * - * @return Twig_TestInterface[] + * @return \Twig_TestInterface[] * * @internal */ @@ -1222,7 +1246,7 @@ class Twig_Environment * * @param string $name The test name * - * @return Twig_Test|false A Twig_Test instance or false if the test does not exist + * @return \Twig_Test|false * * @internal */ @@ -1236,22 +1260,35 @@ class Twig_Environment return $this->tests[$name]; } + foreach ($this->tests as $pattern => $test) { + $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count); + + if ($count) { + if (preg_match('#^'.$pattern.'$#', $name, $matches)) { + array_shift($matches); + $test->setArguments($matches); + + return $test; + } + } + } + return false; } /** * Registers a Function. * - * @param string|Twig_SimpleFunction $name The function name or a Twig_SimpleFunction instance - * @param Twig_FunctionInterface|Twig_SimpleFunction $function + * @param string|TwigFunction $name The function name or a \Twig_SimpleFunction instance + * @param \Twig_FunctionInterface|TwigFunction $function */ public function addFunction($name, $function = null) { - if (!$name instanceof Twig_SimpleFunction && !($function instanceof Twig_SimpleFunction || $function instanceof Twig_FunctionInterface)) { - throw new LogicException('A function must be an instance of Twig_FunctionInterface or Twig_SimpleFunction.'); + if (!$name instanceof TwigFunction && !($function instanceof TwigFunction || $function instanceof \Twig_FunctionInterface)) { + throw new \LogicException('A function must be an instance of \Twig_FunctionInterface or \Twig_SimpleFunction.'); } - if ($name instanceof Twig_SimpleFunction) { + if ($name instanceof TwigFunction) { $function = $name; $name = $function->getName(); } else { @@ -1259,7 +1296,7 @@ class Twig_Environment } if ($this->extensionInitialized) { - throw new LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name)); + throw new \LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name)); } $this->staging->addFunction($name, $function); @@ -1273,7 +1310,7 @@ class Twig_Environment * * @param string $name function name * - * @return Twig_Function|false A Twig_Function instance or false if the function does not exist + * @return \Twig_Function|false * * @internal */ @@ -1301,7 +1338,7 @@ class Twig_Environment } foreach ($this->functionCallbacks as $callback) { - if (false !== $function = call_user_func($callback, $name)) { + if (false !== $function = \call_user_func($callback, $name)) { return $function; } } @@ -1319,7 +1356,7 @@ class Twig_Environment * * Be warned that this method cannot return functions defined with registerUndefinedFunctionCallback. * - * @return Twig_FunctionInterface[] + * @return \Twig_FunctionInterface[] * * @see registerUndefinedFunctionCallback * @@ -1350,10 +1387,10 @@ class Twig_Environment $this->globals = $this->initGlobals(); } - if (!array_key_exists($name, $this->globals)) { + if (!\array_key_exists($name, $this->globals)) { // The deprecation notice must be turned into the following exception in Twig 2.0 @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); - //throw new LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name)); + //throw new \LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name)); } } @@ -1397,7 +1434,7 @@ class Twig_Environment // we don't use array_merge as the context being generally // bigger than globals, this code is faster. foreach ($this->getGlobals() as $key => $value) { - if (!array_key_exists($key, $context)) { + if (!\array_key_exists($key, $context)) { $context[$key] = $value; } } @@ -1444,7 +1481,7 @@ class Twig_Environment { @trigger_error(sprintf('The %s method is deprecated since version 1.23 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); - return Twig_Error_Syntax::computeAlternatives($name, $items); + return SyntaxError::computeAlternatives($name, $items); } /** @@ -1452,19 +1489,20 @@ class Twig_Environment */ protected function initGlobals() { - $globals = array(); + $globals = []; foreach ($this->extensions as $name => $extension) { - if (!$extension instanceof Twig_Extension_GlobalsInterface) { - $m = new ReflectionMethod($extension, 'getGlobals'); + if (!$extension instanceof GlobalsInterface) { + $m = new \ReflectionMethod($extension, 'getGlobals'); - if ('Twig_Extension' !== $m->getDeclaringClass()->getName()) { - @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); + $parentClass = $m->getDeclaringClass()->getName(); + if ('Twig_Extension' !== $parentClass && 'Twig\Extension\AbstractExtension' !== $parentClass) { + @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); } } $extGlob = $extension->getGlobals(); - if (!is_array($extGlob)) { - throw new UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', get_class($extension))); + if (!\is_array($extGlob)) { + throw new \UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', \get_class($extension))); } $globals[] = $extGlob; @@ -1472,7 +1510,7 @@ class Twig_Environment $globals[] = $this->staging->getGlobals(); - return call_user_func_array('array_merge', $globals); + return \call_user_func_array('array_merge', $globals); } /** @@ -1484,13 +1522,13 @@ class Twig_Environment return; } - $this->parsers = new Twig_TokenParserBroker(array(), array(), false); - $this->filters = array(); - $this->functions = array(); - $this->tests = array(); - $this->visitors = array(); - $this->unaryOperators = array(); - $this->binaryOperators = array(); + $this->parsers = new \Twig_TokenParserBroker([], [], false); + $this->filters = []; + $this->functions = []; + $this->tests = []; + $this->visitors = []; + $this->unaryOperators = []; + $this->binaryOperators = []; foreach ($this->extensions as $extension) { $this->initExtension($extension); @@ -1503,14 +1541,14 @@ class Twig_Environment /** * @internal */ - protected function initExtension(Twig_ExtensionInterface $extension) + protected function initExtension(ExtensionInterface $extension) { // filters foreach ($extension->getFilters() as $name => $filter) { - if ($filter instanceof Twig_SimpleFilter) { + if ($filter instanceof TwigFilter) { $name = $filter->getName(); } else { - @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); + @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); } $this->filters[$name] = $filter; @@ -1518,10 +1556,10 @@ class Twig_Environment // functions foreach ($extension->getFunctions() as $name => $function) { - if ($function instanceof Twig_SimpleFunction) { + if ($function instanceof TwigFunction) { $name = $function->getName(); } else { - @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); + @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); } $this->functions[$name] = $function; @@ -1529,10 +1567,10 @@ class Twig_Environment // tests foreach ($extension->getTests() as $name => $test) { - if ($test instanceof Twig_SimpleTest) { + if ($test instanceof TwigTest) { $name = $test->getName(); } else { - @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); + @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); } $this->tests[$name] = $test; @@ -1540,14 +1578,14 @@ class Twig_Environment // token parsers foreach ($extension->getTokenParsers() as $parser) { - if ($parser instanceof Twig_TokenParserInterface) { + if ($parser instanceof TokenParserInterface) { $this->parsers->addTokenParser($parser); - } elseif ($parser instanceof Twig_TokenParserBrokerInterface) { - @trigger_error('Registering a Twig_TokenParserBrokerInterface instance is deprecated since version 1.21.', E_USER_DEPRECATED); + } elseif ($parser instanceof \Twig_TokenParserBrokerInterface) { + @trigger_error('Registering a \Twig_TokenParserBrokerInterface instance is deprecated since version 1.21.', E_USER_DEPRECATED); $this->parsers->addTokenParserBroker($parser); } else { - throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances.'); + throw new \LogicException('getTokenParsers() must return an array of \Twig_TokenParserInterface or \Twig_TokenParserBrokerInterface instances.'); } } @@ -1558,12 +1596,12 @@ class Twig_Environment // operators if ($operators = $extension->getOperators()) { - if (!is_array($operators)) { - 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))); + if (!\is_array($operators)) { + 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))); } - if (2 !== count($operators)) { - throw new InvalidArgumentException(sprintf('"%s::getOperators()" must return an array of 2 elements, got %d.', get_class($extension), count($operators))); + if (2 !== \count($operators)) { + throw new \InvalidArgumentException(sprintf('"%s::getOperators()" must return an array of 2 elements, got %d.', \get_class($extension), \count($operators))); } $this->unaryOperators = array_merge($this->unaryOperators, $operators[0]); @@ -1583,18 +1621,18 @@ class Twig_Environment { $hashParts = array_merge( array_keys($this->extensions), - array( - (int) function_exists('twig_template_get_attributes'), + [ + (int) \function_exists('twig_template_get_attributes'), PHP_MAJOR_VERSION, PHP_MINOR_VERSION, self::VERSION, (int) $this->debug, $this->baseTemplateClass, (int) $this->strictVariables, - ) + ] ); $this->optionsHash = implode(':', $hashParts); } } -class_alias('Twig_Environment', 'Twig\Environment', false); +class_alias('Twig\Environment', 'Twig_Environment'); diff --git a/system/libs/Twig/Error.php b/system/libs/Twig/Error/Error.php old mode 100755 new mode 100644 similarity index 75% rename from system/libs/Twig/Error.php rename to system/libs/Twig/Error/Error.php index 787e0d09..2aa70f15 --- a/system/libs/Twig/Error.php +++ b/system/libs/Twig/Error/Error.php @@ -9,6 +9,11 @@ * file that was distributed with this source code. */ +namespace Twig\Error; + +use Twig\Source; +use Twig\Template; + /** * Twig base exception. * @@ -31,13 +36,12 @@ * * @author Fabien Potencier */ -class Twig_Error extends Exception +class Error extends \Exception { protected $lineno; // to be renamed to name in 2.0 protected $filename; protected $rawMessage; - protected $previous; private $sourcePath; private $sourceCode; @@ -45,25 +49,19 @@ class Twig_Error extends Exception /** * Constructor. * - * Set both the line number and the name to false to - * disable automatic guessing of the original template name - * and line number. - * * Set the line number to -1 to enable its automatic guessing. * Set the name to null to enable its automatic guessing. * - * By default, automatic guessing is enabled. - * - * @param string $message The error message - * @param int $lineno The template line where the error occurred - * @param Twig_Source|string|null $source The source context where the error occurred - * @param Exception $previous The previous exception + * @param string $message The error message + * @param int $lineno The template line where the error occurred + * @param Source|string|null $source The source context where the error occurred + * @param \Exception $previous The previous exception */ - public function __construct($message, $lineno = -1, $source = null, Exception $previous = null) + public function __construct($message, $lineno = -1, $source = null, \Exception $previous = null) { if (null === $source) { $name = null; - } elseif (!$source instanceof Twig_Source) { + } elseif (!$source instanceof Source) { // for compat with the Twig C ext., passing the template name as string is accepted $name = $source; } else { @@ -71,22 +69,11 @@ class Twig_Error extends Exception $this->sourceCode = $source->getCode(); $this->sourcePath = $source->getPath(); } - if (PHP_VERSION_ID < 50300) { - $this->previous = $previous; - parent::__construct(''); - } else { - parent::__construct('', 0, $previous); - } + parent::__construct('', 0, $previous); $this->lineno = $lineno; $this->filename = $name; - - if (-1 === $lineno || null === $name || null === $this->sourcePath) { - $this->guessTemplateInfo(); - } - $this->rawMessage = $message; - $this->updateRepr(); } @@ -186,17 +173,17 @@ class Twig_Error extends Exception /** * Gets the source context of the Twig template where the error occurred. * - * @return Twig_Source|null + * @return Source|null */ public function getSourceContext() { - return $this->filename ? new Twig_Source($this->sourceCode, $this->filename, $this->sourcePath) : null; + return $this->filename ? new Source($this->sourceCode, $this->filename, $this->sourcePath) : null; } /** * Sets the source context of the Twig template where the error occurred. */ - public function setSourceContext(Twig_Source $source = null) + public function setSourceContext(Source $source = null) { if (null === $source) { $this->sourceCode = $this->filename = $this->sourcePath = null; @@ -215,25 +202,6 @@ class Twig_Error extends Exception $this->updateRepr(); } - /** - * For PHP < 5.3.0, provides access to the getPrevious() method. - * - * @param string $method The method name - * @param array $arguments The parameters to be passed to the method - * - * @return Exception The previous exception or null - * - * @throws BadMethodCallException - */ - public function __call($method, $arguments) - { - if ('getprevious' == strtolower($method)) { - return $this->previous; - } - - throw new BadMethodCallException(sprintf('Method "Twig_Error::%s()" does not exist.', $method)); - } - public function appendMessage($rawMessage) { $this->rawMessage .= $rawMessage; @@ -267,7 +235,7 @@ class Twig_Error extends Exception } if ($this->filename) { - if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) { + if (\is_string($this->filename) || (\is_object($this->filename) && method_exists($this->filename, '__toString'))) { $name = sprintf('"%s"', $this->filename); } else { $name = json_encode($this->filename); @@ -296,19 +264,14 @@ class Twig_Error extends Exception $template = null; $templateClass = null; - if (PHP_VERSION_ID >= 50306) { - $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT); - } else { - $backtrace = debug_backtrace(); - } - + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT); foreach ($backtrace as $trace) { - if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) { - $currentClass = get_class($trace['object']); + if (isset($trace['object']) && $trace['object'] instanceof Template && 'Twig_Template' !== \get_class($trace['object'])) { + $currentClass = \get_class($trace['object']); $isEmbedContainer = 0 === strpos($templateClass, $currentClass); if (null === $this->filename || ($this->filename == $trace['object']->getTemplateName() && !$isEmbedContainer)) { $template = $trace['object']; - $templateClass = get_class($trace['object']); + $templateClass = \get_class($trace['object']); } } } @@ -329,17 +292,17 @@ class Twig_Error extends Exception return; } - $r = new ReflectionObject($template); + $r = new \ReflectionObject($template); $file = $r->getFileName(); - $exceptions = array($e = $this); - while (($e instanceof self || method_exists($e, 'getPrevious')) && $e = $e->getPrevious()) { + $exceptions = [$e = $this]; + while ($e instanceof self && $e = $e->getPrevious()) { $exceptions[] = $e; } while ($e = array_pop($exceptions)) { $traces = $e->getTrace(); - array_unshift($traces, array('file' => $e->getFile(), 'line' => $e->getLine())); + array_unshift($traces, ['file' => $e->getFile(), 'line' => $e->getLine()]); while ($trace = array_shift($traces)) { if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) { @@ -359,5 +322,4 @@ class Twig_Error extends Exception } } -class_alias('Twig_Error', 'Twig\Error\Error', false); -class_exists('Twig_Source'); +class_alias('Twig\Error\Error', 'Twig_Error'); diff --git a/system/libs/Twig/Error/Loader.php b/system/libs/Twig/Error/Loader.php deleted file mode 100755 index df566dd7..00000000 --- a/system/libs/Twig/Error/Loader.php +++ /dev/null @@ -1,40 +0,0 @@ - - */ -class Twig_Error_Loader extends Twig_Error -{ - public function __construct($message, $lineno = -1, $source = null, Exception $previous = null) - { - if (PHP_VERSION_ID < 50300) { - $this->previous = $previous; - Exception::__construct(''); - } else { - Exception::__construct('', 0, $previous); - } - $this->appendMessage($message); - $this->setTemplateLine(false); - } -} - -class_alias('Twig_Error_Loader', 'Twig\Error\LoaderError', false); diff --git a/system/libs/Twig/Error/LoaderError.php b/system/libs/Twig/Error/LoaderError.php new file mode 100644 index 00000000..dc5a9f1a --- /dev/null +++ b/system/libs/Twig/Error/LoaderError.php @@ -0,0 +1,23 @@ + + */ +class LoaderError extends Error +{ +} + +class_alias('Twig\Error\LoaderError', 'Twig_Error_Loader'); diff --git a/system/libs/Twig/Error/Runtime.php b/system/libs/Twig/Error/RuntimeError.php old mode 100755 new mode 100644 similarity index 74% rename from system/libs/Twig/Error/Runtime.php rename to system/libs/Twig/Error/RuntimeError.php index 3b24ad3a..9b3f36e0 --- a/system/libs/Twig/Error/Runtime.php +++ b/system/libs/Twig/Error/RuntimeError.php @@ -10,13 +10,15 @@ * file that was distributed with this source code. */ +namespace Twig\Error; + /** * Exception thrown when an error occurs at runtime. * * @author Fabien Potencier */ -class Twig_Error_Runtime extends Twig_Error +class RuntimeError extends Error { } -class_alias('Twig_Error_Runtime', 'Twig\Error\RuntimeError', false); +class_alias('Twig\Error\RuntimeError', 'Twig_Error_Runtime'); diff --git a/system/libs/Twig/Error/Syntax.php b/system/libs/Twig/Error/SyntaxError.php old mode 100755 new mode 100644 similarity index 78% rename from system/libs/Twig/Error/Syntax.php rename to system/libs/Twig/Error/SyntaxError.php index 9d09f217..480e6606 --- a/system/libs/Twig/Error/Syntax.php +++ b/system/libs/Twig/Error/SyntaxError.php @@ -10,12 +10,14 @@ * file that was distributed with this source code. */ +namespace Twig\Error; + /** - * Exception thrown when a syntax error occurs during lexing or parsing of a template. + * \Exception thrown when a syntax error occurs during lexing or parsing of a template. * * @author Fabien Potencier */ -class Twig_Error_Syntax extends Twig_Error +class SyntaxError extends Error { /** * Tweaks the error message to include suggestions. @@ -39,10 +41,10 @@ class Twig_Error_Syntax extends Twig_Error */ public static function computeAlternatives($name, $items) { - $alternatives = array(); + $alternatives = []; foreach ($items as $item) { $lev = levenshtein($name, $item); - if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) { + if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) { $alternatives[$item] = $lev; } } @@ -52,4 +54,4 @@ class Twig_Error_Syntax extends Twig_Error } } -class_alias('Twig_Error_Syntax', 'Twig\Error\SyntaxError', false); +class_alias('Twig\Error\SyntaxError', 'Twig_Error_Syntax'); diff --git a/system/libs/Twig/ExpressionParser.php b/system/libs/Twig/ExpressionParser.php index 4906f903..9066ade1 100755 --- a/system/libs/Twig/ExpressionParser.php +++ b/system/libs/Twig/ExpressionParser.php @@ -10,19 +10,38 @@ * file that was distributed with this source code. */ +namespace Twig; + +use Twig\Error\SyntaxError; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ArrowFunctionExpression; +use Twig\Node\Expression\AssignNameExpression; +use Twig\Node\Expression\Binary\ConcatBinary; +use Twig\Node\Expression\BlockReferenceExpression; +use Twig\Node\Expression\ConditionalExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\GetAttrExpression; +use Twig\Node\Expression\MethodCallExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Expression\ParentExpression; +use Twig\Node\Expression\Unary\NegUnary; +use Twig\Node\Expression\Unary\NotUnary; +use Twig\Node\Expression\Unary\PosUnary; +use Twig\Node\Node; + /** * Parses expressions. * * This parser implements a "Precedence climbing" algorithm. * - * @see http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm - * @see http://en.wikipedia.org/wiki/Operator-precedence_parser + * @see https://www.engr.mun.ca/~theo/Misc/exp_parsing.htm + * @see https://en.wikipedia.org/wiki/Operator-precedence_parser * * @author Fabien Potencier * * @internal */ -class Twig_ExpressionParser +class ExpressionParser { const OPERATOR_LEFT = 1; const OPERATOR_RIGHT = 2; @@ -33,11 +52,11 @@ class Twig_ExpressionParser private $env; - public function __construct(Twig_Parser $parser, $env = null) + public function __construct(Parser $parser, $env = null) { $this->parser = $parser; - if ($env instanceof Twig_Environment) { + if ($env instanceof Environment) { $this->env = $env; $this->unaryOperators = $env->getUnaryOperators(); $this->binaryOperators = $env->getBinaryOperators(); @@ -50,8 +69,12 @@ class Twig_ExpressionParser } } - public function parseExpression($precedence = 0) + public function parseExpression($precedence = 0, $allowArrow = false) { + if ($allowArrow && $arrow = $this->parseArrow()) { + return $arrow; + } + $expr = $this->getPrimary(); $token = $this->parser->getCurrentToken(); while ($this->isBinary($token) && $this->binaryOperators[$token->getValue()]['precedence'] >= $precedence) { @@ -63,7 +86,7 @@ class Twig_ExpressionParser } elseif ('is' === $token->getValue()) { $expr = $this->parseTestExpression($expr); } elseif (isset($op['callable'])) { - $expr = call_user_func($op['callable'], $this->parser, $expr); + $expr = \call_user_func($op['callable'], $this->parser, $expr); } else { $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']); $class = $op['class']; @@ -80,6 +103,64 @@ class Twig_ExpressionParser return $expr; } + /** + * @return ArrowFunctionExpression|null + */ + private function parseArrow() + { + $stream = $this->parser->getStream(); + + // short array syntax (one argument, no parentheses)? + if ($stream->look(1)->test(Token::ARROW_TYPE)) { + $line = $stream->getCurrent()->getLine(); + $token = $stream->expect(Token::NAME_TYPE); + $names = [new AssignNameExpression($token->getValue(), $token->getLine())]; + $stream->expect(Token::ARROW_TYPE); + + return new ArrowFunctionExpression($this->parseExpression(0), new Node($names), $line); + } + + // first, determine if we are parsing an arrow function by finding => (long form) + $i = 0; + if (!$stream->look($i)->test(Token::PUNCTUATION_TYPE, '(')) { + return null; + } + ++$i; + while (true) { + // variable name + ++$i; + if (!$stream->look($i)->test(Token::PUNCTUATION_TYPE, ',')) { + break; + } + ++$i; + } + if (!$stream->look($i)->test(Token::PUNCTUATION_TYPE, ')')) { + return null; + } + ++$i; + if (!$stream->look($i)->test(Token::ARROW_TYPE)) { + return null; + } + + // yes, let's parse it properly + $token = $stream->expect(Token::PUNCTUATION_TYPE, '('); + $line = $token->getLine(); + + $names = []; + while (true) { + $token = $stream->expect(Token::NAME_TYPE); + $names[] = new AssignNameExpression($token->getValue(), $token->getLine()); + + if (!$stream->nextIf(Token::PUNCTUATION_TYPE, ',')) { + break; + } + } + $stream->expect(Token::PUNCTUATION_TYPE, ')'); + $stream->expect(Token::ARROW_TYPE); + + return new ArrowFunctionExpression($this->parseExpression(0), new Node($names), $line); + } + protected function getPrimary() { $token = $this->parser->getCurrentToken(); @@ -91,10 +172,10 @@ class Twig_ExpressionParser $class = $operator['class']; return $this->parsePostfixExpression(new $class($expr, $token->getLine())); - } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '(')) { + } elseif ($token->test(Token::PUNCTUATION_TYPE, '(')) { $this->parser->getStream()->next(); $expr = $this->parseExpression(); - $this->parser->getStream()->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed'); + $this->parser->getStream()->expect(Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed'); return $this->parsePostfixExpression($expr); } @@ -104,92 +185,95 @@ class Twig_ExpressionParser protected function parseConditionalExpression($expr) { - while ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, '?')) { - if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { + while ($this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, '?')) { + if (!$this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, ':')) { $expr2 = $this->parseExpression(); - if ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { + if ($this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, ':')) { $expr3 = $this->parseExpression(); } else { - $expr3 = new Twig_Node_Expression_Constant('', $this->parser->getCurrentToken()->getLine()); + $expr3 = new ConstantExpression('', $this->parser->getCurrentToken()->getLine()); } } else { $expr2 = $expr; $expr3 = $this->parseExpression(); } - $expr = new Twig_Node_Expression_Conditional($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine()); + $expr = new ConditionalExpression($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine()); } return $expr; } - protected function isUnary(Twig_Token $token) + protected function isUnary(Token $token) { - return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]); + return $token->test(Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]); } - protected function isBinary(Twig_Token $token) + protected function isBinary(Token $token) { - return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]); + return $token->test(Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]); } public function parsePrimaryExpression() { $token = $this->parser->getCurrentToken(); switch ($token->getType()) { - case Twig_Token::NAME_TYPE: + case Token::NAME_TYPE: $this->parser->getStream()->next(); switch ($token->getValue()) { case 'true': case 'TRUE': - $node = new Twig_Node_Expression_Constant(true, $token->getLine()); + $node = new ConstantExpression(true, $token->getLine()); break; case 'false': case 'FALSE': - $node = new Twig_Node_Expression_Constant(false, $token->getLine()); + $node = new ConstantExpression(false, $token->getLine()); break; case 'none': case 'NONE': case 'null': case 'NULL': - $node = new Twig_Node_Expression_Constant(null, $token->getLine()); + $node = new ConstantExpression(null, $token->getLine()); break; default: if ('(' === $this->parser->getCurrentToken()->getValue()) { $node = $this->getFunctionNode($token->getValue(), $token->getLine()); } else { - $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine()); + $node = new NameExpression($token->getValue(), $token->getLine()); } } break; - case Twig_Token::NUMBER_TYPE: + case Token::NUMBER_TYPE: $this->parser->getStream()->next(); - $node = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); + $node = new ConstantExpression($token->getValue(), $token->getLine()); break; - case Twig_Token::STRING_TYPE: - case Twig_Token::INTERPOLATION_START_TYPE: + case Token::STRING_TYPE: + case Token::INTERPOLATION_START_TYPE: $node = $this->parseStringExpression(); break; - case Twig_Token::OPERATOR_TYPE: - if (preg_match(Twig_Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) { + case Token::OPERATOR_TYPE: + if (preg_match(Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) { // in this context, string operators are variable names $this->parser->getStream()->next(); - $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine()); + $node = new NameExpression($token->getValue(), $token->getLine()); break; } elseif (isset($this->unaryOperators[$token->getValue()])) { $class = $this->unaryOperators[$token->getValue()]['class']; - $ref = new ReflectionClass($class); - $negClass = 'Twig_Node_Expression_Unary_Neg'; - $posClass = 'Twig_Node_Expression_Unary_Pos'; - if (!(in_array($ref->getName(), array($negClass, $posClass)) || $ref->isSubclassOf($negClass) || $ref->isSubclassOf($posClass))) { - throw new Twig_Error_Syntax(sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); + $ref = new \ReflectionClass($class); + $negClass = 'Twig\Node\Expression\Unary\NegUnary'; + $posClass = 'Twig\Node\Expression\Unary\PosUnary'; + if (!(\in_array($ref->getName(), [$negClass, $posClass, 'Twig_Node_Expression_Unary_Neg', 'Twig_Node_Expression_Unary_Pos']) + || $ref->isSubclassOf($negClass) || $ref->isSubclassOf($posClass) + || $ref->isSubclassOf('Twig_Node_Expression_Unary_Neg') || $ref->isSubclassOf('Twig_Node_Expression_Unary_Pos')) + ) { + throw new SyntaxError(sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); } $this->parser->getStream()->next(); @@ -199,13 +283,16 @@ class Twig_ExpressionParser break; } + // no break default: - if ($token->test(Twig_Token::PUNCTUATION_TYPE, '[')) { + if ($token->test(Token::PUNCTUATION_TYPE, '[')) { $node = $this->parseArrayExpression(); - } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) { + } elseif ($token->test(Token::PUNCTUATION_TYPE, '{')) { $node = $this->parseHashExpression(); + } elseif ($token->test(Token::OPERATOR_TYPE, '=') && ('==' === $this->parser->getStream()->look(-1)->getValue() || '!=' === $this->parser->getStream()->look(-1)->getValue())) { + 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()); } else { - throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s".', Twig_Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); + throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s".', Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); } } @@ -216,16 +303,16 @@ class Twig_ExpressionParser { $stream = $this->parser->getStream(); - $nodes = array(); + $nodes = []; // a string cannot be followed by another string in a single expression $nextCanBeString = true; while (true) { - if ($nextCanBeString && $token = $stream->nextIf(Twig_Token::STRING_TYPE)) { - $nodes[] = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); + if ($nextCanBeString && $token = $stream->nextIf(Token::STRING_TYPE)) { + $nodes[] = new ConstantExpression($token->getValue(), $token->getLine()); $nextCanBeString = false; - } elseif ($stream->nextIf(Twig_Token::INTERPOLATION_START_TYPE)) { + } elseif ($stream->nextIf(Token::INTERPOLATION_START_TYPE)) { $nodes[] = $this->parseExpression(); - $stream->expect(Twig_Token::INTERPOLATION_END_TYPE); + $stream->expect(Token::INTERPOLATION_END_TYPE); $nextCanBeString = true; } else { break; @@ -234,7 +321,7 @@ class Twig_ExpressionParser $expr = array_shift($nodes); foreach ($nodes as $node) { - $expr = new Twig_Node_Expression_Binary_Concat($expr, $node, $node->getTemplateLine()); + $expr = new ConcatBinary($expr, $node, $node->getTemplateLine()); } return $expr; @@ -243,16 +330,16 @@ class Twig_ExpressionParser public function parseArrayExpression() { $stream = $this->parser->getStream(); - $stream->expect(Twig_Token::PUNCTUATION_TYPE, '[', 'An array element was expected'); + $stream->expect(Token::PUNCTUATION_TYPE, '[', 'An array element was expected'); - $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine()); + $node = new ArrayExpression([], $stream->getCurrent()->getLine()); $first = true; - while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { + while (!$stream->test(Token::PUNCTUATION_TYPE, ']')) { if (!$first) { - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma'); + $stream->expect(Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma'); // trailing ,? - if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { + if ($stream->test(Token::PUNCTUATION_TYPE, ']')) { break; } } @@ -260,7 +347,7 @@ class Twig_ExpressionParser $node->addElement($this->parseExpression()); } - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed'); + $stream->expect(Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed'); return $node; } @@ -268,16 +355,16 @@ class Twig_ExpressionParser public function parseHashExpression() { $stream = $this->parser->getStream(); - $stream->expect(Twig_Token::PUNCTUATION_TYPE, '{', 'A hash element was expected'); + $stream->expect(Token::PUNCTUATION_TYPE, '{', 'A hash element was expected'); - $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine()); + $node = new ArrayExpression([], $stream->getCurrent()->getLine()); $first = true; - while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) { + while (!$stream->test(Token::PUNCTUATION_TYPE, '}')) { if (!$first) { - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma'); + $stream->expect(Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma'); // trailing ,? - if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) { + if ($stream->test(Token::PUNCTUATION_TYPE, '}')) { break; } } @@ -289,22 +376,22 @@ class Twig_ExpressionParser // * a string -- 'a' // * a name, which is equivalent to a string -- a // * an expression, which must be enclosed in parentheses -- (1 + 2) - if (($token = $stream->nextIf(Twig_Token::STRING_TYPE)) || ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) || $token = $stream->nextIf(Twig_Token::NUMBER_TYPE)) { - $key = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); - } elseif ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { + if (($token = $stream->nextIf(Token::STRING_TYPE)) || ($token = $stream->nextIf(Token::NAME_TYPE)) || $token = $stream->nextIf(Token::NUMBER_TYPE)) { + $key = new ConstantExpression($token->getValue(), $token->getLine()); + } elseif ($stream->test(Token::PUNCTUATION_TYPE, '(')) { $key = $this->parseExpression(); } else { $current = $stream->getCurrent(); - throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s".', Twig_Token::typeToEnglish($current->getType()), $current->getValue()), $current->getLine(), $stream->getSourceContext()); + 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()); } - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)'); + $stream->expect(Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)'); $value = $this->parseExpression(); $node->addElement($value, $key); } - $stream->expect(Twig_Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed'); + $stream->expect(Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed'); return $node; } @@ -313,7 +400,7 @@ class Twig_ExpressionParser { while (true) { $token = $this->parser->getCurrentToken(); - if ($token->getType() == Twig_Token::PUNCTUATION_TYPE) { + if (Token::PUNCTUATION_TYPE == $token->getType()) { if ('.' == $token->getValue() || '[' == $token->getValue()) { $node = $this->parseSubscriptExpression($node); } elseif ('|' == $token->getValue()) { @@ -334,37 +421,37 @@ class Twig_ExpressionParser switch ($name) { case 'parent': $this->parseArguments(); - if (!count($this->parser->getBlockStack())) { - throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden.', $line, $this->parser->getStream()->getSourceContext()); + if (!\count($this->parser->getBlockStack())) { + throw new SyntaxError('Calling "parent" outside a block is forbidden.', $line, $this->parser->getStream()->getSourceContext()); } if (!$this->parser->getParent() && !$this->parser->hasTraits()) { - throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden.', $line, $this->parser->getStream()->getSourceContext()); + throw new SyntaxError('Calling "parent" on a template that does not extend nor "use" another template is forbidden.', $line, $this->parser->getStream()->getSourceContext()); } - return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line); + return new ParentExpression($this->parser->peekBlockStack(), $line); case 'block': $args = $this->parseArguments(); - if (count($args) < 1) { - throw new Twig_Error_Syntax('The "block" function takes one argument (the block name).', $line, $this->parser->getStream()->getSourceContext()); + if (\count($args) < 1) { + throw new SyntaxError('The "block" function takes one argument (the block name).', $line, $this->parser->getStream()->getSourceContext()); } - return new Twig_Node_Expression_BlockReference($args->getNode(0), count($args) > 1 ? $args->getNode(1) : null, $line); + return new BlockReferenceExpression($args->getNode(0), \count($args) > 1 ? $args->getNode(1) : null, $line); case 'attribute': $args = $this->parseArguments(); - if (count($args) < 2) { - throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes).', $line, $this->parser->getStream()->getSourceContext()); + if (\count($args) < 2) { + throw new SyntaxError('The "attribute" function takes at least two arguments (the variable and the attributes).', $line, $this->parser->getStream()->getSourceContext()); } - return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : null, Twig_Template::ANY_CALL, $line); + return new GetAttrExpression($args->getNode(0), $args->getNode(1), \count($args) > 2 ? $args->getNode(2) : null, Template::ANY_CALL, $line); default: if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) { - $arguments = new Twig_Node_Expression_Array(array(), $line); + $arguments = new ArrayExpression([], $line); foreach ($this->parseArguments() as $n) { $arguments->addElement($n); } - $node = new Twig_Node_Expression_MethodCall($alias['node'], $alias['name'], $arguments, $line); + $node = new MethodCallExpression($alias['node'], $alias['name'], $arguments, $line); $node->setAttribute('safe', true); return $node; @@ -382,81 +469,81 @@ class Twig_ExpressionParser $stream = $this->parser->getStream(); $token = $stream->next(); $lineno = $token->getLine(); - $arguments = new Twig_Node_Expression_Array(array(), $lineno); - $type = Twig_Template::ANY_CALL; - if ($token->getValue() == '.') { + $arguments = new ArrayExpression([], $lineno); + $type = Template::ANY_CALL; + if ('.' == $token->getValue()) { $token = $stream->next(); if ( - $token->getType() == Twig_Token::NAME_TYPE + Token::NAME_TYPE == $token->getType() || - $token->getType() == Twig_Token::NUMBER_TYPE + Token::NUMBER_TYPE == $token->getType() || - ($token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue())) + (Token::OPERATOR_TYPE == $token->getType() && preg_match(Lexer::REGEX_NAME, $token->getValue())) ) { - $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno); + $arg = new ConstantExpression($token->getValue(), $lineno); - if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { - $type = Twig_Template::METHOD_CALL; + if ($stream->test(Token::PUNCTUATION_TYPE, '(')) { + $type = Template::METHOD_CALL; foreach ($this->parseArguments() as $n) { $arguments->addElement($n); } } } else { - throw new Twig_Error_Syntax('Expected name or number.', $lineno, $stream->getSourceContext()); + throw new SyntaxError('Expected name or number.', $lineno, $stream->getSourceContext()); } - if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) { - if (!$arg instanceof Twig_Node_Expression_Constant) { - throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s").', $node->getAttribute('name')), $token->getLine(), $stream->getSourceContext()); + if ($node instanceof NameExpression && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) { + if (!$arg instanceof ConstantExpression) { + throw new SyntaxError(sprintf('Dynamic macro names are not supported (called on "%s").', $node->getAttribute('name')), $token->getLine(), $stream->getSourceContext()); } $name = $arg->getAttribute('value'); if ($this->parser->isReservedMacroName($name)) { - throw new Twig_Error_Syntax(sprintf('"%s" cannot be called as macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext()); + throw new SyntaxError(sprintf('"%s" cannot be called as macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext()); } - $node = new Twig_Node_Expression_MethodCall($node, 'get'.$name, $arguments, $lineno); + $node = new MethodCallExpression($node, 'get'.$name, $arguments, $lineno); $node->setAttribute('safe', true); return $node; } } else { - $type = Twig_Template::ARRAY_CALL; + $type = Template::ARRAY_CALL; // slice? $slice = false; - if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) { + if ($stream->test(Token::PUNCTUATION_TYPE, ':')) { $slice = true; - $arg = new Twig_Node_Expression_Constant(0, $token->getLine()); + $arg = new ConstantExpression(0, $token->getLine()); } else { $arg = $this->parseExpression(); } - if ($stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { + if ($stream->nextIf(Token::PUNCTUATION_TYPE, ':')) { $slice = true; } if ($slice) { - if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { - $length = new Twig_Node_Expression_Constant(null, $token->getLine()); + if ($stream->test(Token::PUNCTUATION_TYPE, ']')) { + $length = new ConstantExpression(null, $token->getLine()); } else { $length = $this->parseExpression(); } $class = $this->getFilterNodeClass('slice', $token->getLine()); - $arguments = new Twig_Node(array($arg, $length)); - $filter = new $class($node, new Twig_Node_Expression_Constant('slice', $token->getLine()), $arguments, $token->getLine()); + $arguments = new Node([$arg, $length]); + $filter = new $class($node, new ConstantExpression('slice', $token->getLine()), $arguments, $token->getLine()); - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); + $stream->expect(Token::PUNCTUATION_TYPE, ']'); return $filter; } - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); + $stream->expect(Token::PUNCTUATION_TYPE, ']'); } - return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno); + return new GetAttrExpression($node, $arg, $arguments, $type, $lineno); } public function parseFilterExpression($node) @@ -469,20 +556,20 @@ class Twig_ExpressionParser public function parseFilterExpressionRaw($node, $tag = null) { while (true) { - $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE); + $token = $this->parser->getStream()->expect(Token::NAME_TYPE); - $name = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); - if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '(')) { - $arguments = new Twig_Node(); + $name = new ConstantExpression($token->getValue(), $token->getLine()); + if (!$this->parser->getStream()->test(Token::PUNCTUATION_TYPE, '(')) { + $arguments = new Node(); } else { - $arguments = $this->parseArguments(true); + $arguments = $this->parseArguments(true, false, true); } $class = $this->getFilterNodeClass($name->getAttribute('value'), $token->getLine()); $node = new $class($node, $name, $arguments, $token->getLine(), $tag); - if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '|')) { + if (!$this->parser->getStream()->test(Token::PUNCTUATION_TYPE, '|')) { break; } @@ -498,32 +585,32 @@ class Twig_ExpressionParser * @param bool $namedArguments Whether to allow named arguments or not * @param bool $definition Whether we are parsing arguments for a function definition * - * @return Twig_Node + * @return Node * - * @throws Twig_Error_Syntax + * @throws SyntaxError */ - public function parseArguments($namedArguments = false, $definition = false) + public function parseArguments($namedArguments = false, $definition = false, $allowArrow = false) { - $args = array(); + $args = []; $stream = $this->parser->getStream(); - $stream->expect(Twig_Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis'); - while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ')')) { + $stream->expect(Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis'); + while (!$stream->test(Token::PUNCTUATION_TYPE, ')')) { if (!empty($args)) { - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma'); + $stream->expect(Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma'); } if ($definition) { - $token = $stream->expect(Twig_Token::NAME_TYPE, null, 'An argument must be a name'); - $value = new Twig_Node_Expression_Name($token->getValue(), $this->parser->getCurrentToken()->getLine()); + $token = $stream->expect(Token::NAME_TYPE, null, 'An argument must be a name'); + $value = new NameExpression($token->getValue(), $this->parser->getCurrentToken()->getLine()); } else { - $value = $this->parseExpression(); + $value = $this->parseExpression(0, $allowArrow); } $name = null; - if ($namedArguments && $token = $stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) { - if (!$value instanceof Twig_Node_Expression_Name) { - throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given.', get_class($value)), $token->getLine(), $stream->getSourceContext()); + if ($namedArguments && $token = $stream->nextIf(Token::OPERATOR_TYPE, '=')) { + if (!$value instanceof NameExpression) { + throw new SyntaxError(sprintf('A parameter name must be a string, "%s" given.', \get_class($value)), $token->getLine(), $stream->getSourceContext()); } $name = $value->getAttribute('name'); @@ -531,17 +618,17 @@ class Twig_ExpressionParser $value = $this->parsePrimaryExpression(); if (!$this->checkConstantExpression($value)) { - throw new Twig_Error_Syntax(sprintf('A default value for an argument must be a constant (a boolean, a string, a number, or an array).'), $token->getLine(), $stream->getSourceContext()); + 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()); } } else { - $value = $this->parseExpression(); + $value = $this->parseExpression(0, $allowArrow); } } if ($definition) { if (null === $name) { $name = $value->getAttribute('name'); - $value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine()); + $value = new ConstantExpression(null, $this->parser->getCurrentToken()->getLine()); } $args[$name] = $value; } else { @@ -552,58 +639,64 @@ class Twig_ExpressionParser } } } - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis'); + $stream->expect(Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis'); - return new Twig_Node($args); + return new Node($args); } public function parseAssignmentExpression() { $stream = $this->parser->getStream(); - $targets = array(); + $targets = []; while (true) { - $token = $stream->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to'); - $value = $token->getValue(); - if (in_array(strtolower($value), array('true', 'false', 'none', 'null'))) { - throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s".', $value), $token->getLine(), $stream->getSourceContext()); + $token = $this->parser->getCurrentToken(); + if ($stream->test(Token::OPERATOR_TYPE) && preg_match(Lexer::REGEX_NAME, $token->getValue())) { + // in this context, string operators are variable names + $this->parser->getStream()->next(); + } else { + $stream->expect(Token::NAME_TYPE, null, 'Only variables can be assigned to'); } - $targets[] = new Twig_Node_Expression_AssignName($value, $token->getLine()); + $value = $token->getValue(); + if (\in_array(strtolower($value), ['true', 'false', 'none', 'null'])) { + throw new SyntaxError(sprintf('You cannot assign a value to "%s".', $value), $token->getLine(), $stream->getSourceContext()); + } + $targets[] = new AssignNameExpression($value, $token->getLine()); - if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { + if (!$stream->nextIf(Token::PUNCTUATION_TYPE, ',')) { break; } } - return new Twig_Node($targets); + return new Node($targets); } public function parseMultitargetExpression() { - $targets = array(); + $targets = []; while (true) { $targets[] = $this->parseExpression(); - if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { + if (!$this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, ',')) { break; } } - return new Twig_Node($targets); + return new Node($targets); } - private function parseNotTestExpression(Twig_NodeInterface $node) + private function parseNotTestExpression(\Twig_NodeInterface $node) { - return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($node), $this->parser->getCurrentToken()->getLine()); + return new NotUnary($this->parseTestExpression($node), $this->parser->getCurrentToken()->getLine()); } - private function parseTestExpression(Twig_NodeInterface $node) + private function parseTestExpression(\Twig_NodeInterface $node) { $stream = $this->parser->getStream(); list($name, $test) = $this->getTest($node->getTemplateLine()); $class = $this->getTestNodeClass($test); $arguments = null; - if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { - $arguments = $this->parser->getExpressionParser()->parseArguments(true); + if ($stream->test(Token::PUNCTUATION_TYPE, '(')) { + $arguments = $this->parseArguments(true); } return new $class($node, $name, $arguments, $this->parser->getCurrentToken()->getLine()); @@ -612,24 +705,24 @@ class Twig_ExpressionParser private function getTest($line) { $stream = $this->parser->getStream(); - $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); + $name = $stream->expect(Token::NAME_TYPE)->getValue(); if ($test = $this->env->getTest($name)) { - return array($name, $test); + return [$name, $test]; } - if ($stream->test(Twig_Token::NAME_TYPE)) { + if ($stream->test(Token::NAME_TYPE)) { // try 2-words tests $name = $name.' '.$this->parser->getCurrentToken()->getValue(); if ($test = $this->env->getTest($name)) { $stream->next(); - return array($name, $test); + return [$name, $test]; } } - $e = new Twig_Error_Syntax(sprintf('Unknown "%s" test.', $name), $line, $stream->getSourceContext()); + $e = new SyntaxError(sprintf('Unknown "%s" test.', $name), $line, $stream->getSourceContext()); $e->addSuggestions($name, array_keys($this->env->getTests())); throw $e; @@ -637,10 +730,10 @@ class Twig_ExpressionParser private function getTestNodeClass($test) { - if ($test instanceof Twig_SimpleTest && $test->isDeprecated()) { + if ($test instanceof TwigTest && $test->isDeprecated()) { $stream = $this->parser->getStream(); $message = sprintf('Twig Test "%s" is deprecated', $test->getName()); - if (!is_bool($test->getDeprecatedVersion())) { + if (!\is_bool($test->getDeprecatedVersion())) { $message .= sprintf(' since version %s', $test->getDeprecatedVersion()); } if ($test->getAlternative()) { @@ -652,25 +745,25 @@ class Twig_ExpressionParser @trigger_error($message, E_USER_DEPRECATED); } - if ($test instanceof Twig_SimpleTest) { + if ($test instanceof TwigTest) { return $test->getNodeClass(); } - return $test instanceof Twig_Test_Node ? $test->getClass() : 'Twig_Node_Expression_Test'; + return $test instanceof \Twig_Test_Node ? $test->getClass() : 'Twig\Node\Expression\TestExpression'; } protected function getFunctionNodeClass($name, $line) { if (false === $function = $this->env->getFunction($name)) { - $e = new Twig_Error_Syntax(sprintf('Unknown "%s" function.', $name), $line, $this->parser->getStream()->getSourceContext()); + $e = new SyntaxError(sprintf('Unknown "%s" function.', $name), $line, $this->parser->getStream()->getSourceContext()); $e->addSuggestions($name, array_keys($this->env->getFunctions())); throw $e; } - if ($function instanceof Twig_SimpleFunction && $function->isDeprecated()) { + if ($function instanceof TwigFunction && $function->isDeprecated()) { $message = sprintf('Twig Function "%s" is deprecated', $function->getName()); - if (!is_bool($function->getDeprecatedVersion())) { + if (!\is_bool($function->getDeprecatedVersion())) { $message .= sprintf(' since version %s', $function->getDeprecatedVersion()); } if ($function->getAlternative()) { @@ -682,25 +775,25 @@ class Twig_ExpressionParser @trigger_error($message, E_USER_DEPRECATED); } - if ($function instanceof Twig_SimpleFunction) { + if ($function instanceof TwigFunction) { return $function->getNodeClass(); } - return $function instanceof Twig_Function_Node ? $function->getClass() : 'Twig_Node_Expression_Function'; + return $function instanceof \Twig_Function_Node ? $function->getClass() : 'Twig\Node\Expression\FunctionExpression'; } protected function getFilterNodeClass($name, $line) { if (false === $filter = $this->env->getFilter($name)) { - $e = new Twig_Error_Syntax(sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getStream()->getSourceContext()); + $e = new SyntaxError(sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getStream()->getSourceContext()); $e->addSuggestions($name, array_keys($this->env->getFilters())); throw $e; } - if ($filter instanceof Twig_SimpleFilter && $filter->isDeprecated()) { + if ($filter instanceof TwigFilter && $filter->isDeprecated()) { $message = sprintf('Twig Filter "%s" is deprecated', $filter->getName()); - if (!is_bool($filter->getDeprecatedVersion())) { + if (!\is_bool($filter->getDeprecatedVersion())) { $message .= sprintf(' since version %s', $filter->getDeprecatedVersion()); } if ($filter->getAlternative()) { @@ -712,18 +805,18 @@ class Twig_ExpressionParser @trigger_error($message, E_USER_DEPRECATED); } - if ($filter instanceof Twig_SimpleFilter) { + if ($filter instanceof TwigFilter) { return $filter->getNodeClass(); } - return $filter instanceof Twig_Filter_Node ? $filter->getClass() : 'Twig_Node_Expression_Filter'; + return $filter instanceof \Twig_Filter_Node ? $filter->getClass() : 'Twig\Node\Expression\FilterExpression'; } // checks that the node only contains "constant" elements - protected function checkConstantExpression(Twig_NodeInterface $node) + protected function checkConstantExpression(\Twig_NodeInterface $node) { - if (!($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array - || $node instanceof Twig_Node_Expression_Unary_Neg || $node instanceof Twig_Node_Expression_Unary_Pos + if (!($node instanceof ConstantExpression || $node instanceof ArrayExpression + || $node instanceof NegUnary || $node instanceof PosUnary )) { return false; } @@ -738,4 +831,4 @@ class Twig_ExpressionParser } } -class_alias('Twig_ExpressionParser', 'Twig\ExpressionParser', false); +class_alias('Twig\ExpressionParser', 'Twig_ExpressionParser'); diff --git a/system/libs/Twig/Extension.php b/system/libs/Twig/Extension/AbstractExtension.php old mode 100755 new mode 100644 similarity index 62% rename from system/libs/Twig/Extension.php rename to system/libs/Twig/Extension/AbstractExtension.php index 38084495..fa3245b2 --- a/system/libs/Twig/Extension.php +++ b/system/libs/Twig/Extension/AbstractExtension.php @@ -9,51 +9,55 @@ * file that was distributed with this source code. */ -abstract class Twig_Extension implements Twig_ExtensionInterface +namespace Twig\Extension; + +use Twig\Environment; + +abstract class AbstractExtension implements ExtensionInterface { /** - * @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead + * @deprecated since 1.23 (to be removed in 2.0), implement \Twig_Extension_InitRuntimeInterface instead */ - public function initRuntime(Twig_Environment $environment) + public function initRuntime(Environment $environment) { } public function getTokenParsers() { - return array(); + return []; } public function getNodeVisitors() { - return array(); + return []; } public function getFilters() { - return array(); + return []; } public function getTests() { - return array(); + return []; } public function getFunctions() { - return array(); + return []; } public function getOperators() { - return array(); + return []; } /** - * @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_GlobalsInterface instead + * @deprecated since 1.23 (to be removed in 2.0), implement \Twig_Extension_GlobalsInterface instead */ public function getGlobals() { - return array(); + return []; } /** @@ -61,9 +65,8 @@ abstract class Twig_Extension implements Twig_ExtensionInterface */ public function getName() { - return get_class($this); + return \get_class($this); } } -class_alias('Twig_Extension', 'Twig\Extension\AbstractExtension', false); -class_exists('Twig_Environment'); +class_alias('Twig\Extension\AbstractExtension', 'Twig_Extension'); diff --git a/system/libs/Twig/Extension/Core.php b/system/libs/Twig/Extension/Core.php deleted file mode 100755 index 34f9ef7d..00000000 --- a/system/libs/Twig/Extension/Core.php +++ /dev/null @@ -1,1612 +0,0 @@ -escapers[$strategy] = $callable; - } - - /** - * Gets all defined escapers. - * - * @return array An array of escapers - */ - public function getEscapers() - { - return $this->escapers; - } - - /** - * Sets the default format to be used by the date filter. - * - * @param string $format The default date format string - * @param string $dateIntervalFormat The default date interval format string - */ - public function setDateFormat($format = null, $dateIntervalFormat = null) - { - if (null !== $format) { - $this->dateFormats[0] = $format; - } - - if (null !== $dateIntervalFormat) { - $this->dateFormats[1] = $dateIntervalFormat; - } - } - - /** - * Gets the default format to be used by the date filter. - * - * @return array The default date format string and the default date interval format string - */ - public function getDateFormat() - { - return $this->dateFormats; - } - - /** - * Sets the default timezone to be used by the date filter. - * - * @param DateTimeZone|string $timezone The default timezone string or a DateTimeZone object - */ - public function setTimezone($timezone) - { - $this->timezone = $timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone); - } - - /** - * Gets the default timezone to be used by the date filter. - * - * @return DateTimeZone The default timezone currently in use - */ - public function getTimezone() - { - if (null === $this->timezone) { - $this->timezone = new DateTimeZone(date_default_timezone_get()); - } - - return $this->timezone; - } - - /** - * Sets the default format to be used by the number_format filter. - * - * @param int $decimal the number of decimal places to use - * @param string $decimalPoint the character(s) to use for the decimal point - * @param string $thousandSep the character(s) to use for the thousands separator - */ - public function setNumberFormat($decimal, $decimalPoint, $thousandSep) - { - $this->numberFormat = array($decimal, $decimalPoint, $thousandSep); - } - - /** - * Get the default format used by the number_format filter. - * - * @return array The arguments for number_format() - */ - public function getNumberFormat() - { - return $this->numberFormat; - } - - public function getTokenParsers() - { - return array( - new Twig_TokenParser_For(), - new Twig_TokenParser_If(), - new Twig_TokenParser_Extends(), - new Twig_TokenParser_Include(), - new Twig_TokenParser_Block(), - new Twig_TokenParser_Use(), - new Twig_TokenParser_Filter(), - new Twig_TokenParser_Macro(), - new Twig_TokenParser_Import(), - new Twig_TokenParser_From(), - new Twig_TokenParser_Set(), - new Twig_TokenParser_Spaceless(), - new Twig_TokenParser_Flush(), - new Twig_TokenParser_Do(), - new Twig_TokenParser_Embed(), - new Twig_TokenParser_With(), - ); - } - - public function getFilters() - { - $filters = array( - // formatting filters - new Twig_SimpleFilter('date', 'twig_date_format_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('date_modify', 'twig_date_modify_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('format', 'sprintf'), - new Twig_SimpleFilter('replace', 'twig_replace_filter'), - new Twig_SimpleFilter('number_format', 'twig_number_format_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('abs', 'abs'), - new Twig_SimpleFilter('round', 'twig_round'), - - // encoding - new Twig_SimpleFilter('url_encode', 'twig_urlencode_filter'), - new Twig_SimpleFilter('json_encode', 'twig_jsonencode_filter'), - new Twig_SimpleFilter('convert_encoding', 'twig_convert_encoding'), - - // string filters - new Twig_SimpleFilter('title', 'twig_title_string_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('capitalize', 'twig_capitalize_string_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('upper', 'strtoupper'), - new Twig_SimpleFilter('lower', 'strtolower'), - new Twig_SimpleFilter('striptags', 'strip_tags'), - new Twig_SimpleFilter('trim', 'twig_trim_filter'), - new Twig_SimpleFilter('nl2br', 'nl2br', array('pre_escape' => 'html', 'is_safe' => array('html'))), - - // array helpers - new Twig_SimpleFilter('join', 'twig_join_filter'), - new Twig_SimpleFilter('split', 'twig_split_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('sort', 'twig_sort_filter'), - new Twig_SimpleFilter('merge', 'twig_array_merge'), - new Twig_SimpleFilter('batch', 'twig_array_batch'), - - // string/array filters - new Twig_SimpleFilter('reverse', 'twig_reverse_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('length', 'twig_length_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('slice', 'twig_slice', array('needs_environment' => true)), - new Twig_SimpleFilter('first', 'twig_first', array('needs_environment' => true)), - new Twig_SimpleFilter('last', 'twig_last', array('needs_environment' => true)), - - // iteration and runtime - new Twig_SimpleFilter('default', '_twig_default_filter', array('node_class' => 'Twig_Node_Expression_Filter_Default')), - new Twig_SimpleFilter('keys', 'twig_get_array_keys_filter'), - - // escaping - new Twig_SimpleFilter('escape', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')), - new Twig_SimpleFilter('e', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')), - ); - - if (function_exists('mb_get_info')) { - $filters[] = new Twig_SimpleFilter('upper', 'twig_upper_filter', array('needs_environment' => true)); - $filters[] = new Twig_SimpleFilter('lower', 'twig_lower_filter', array('needs_environment' => true)); - } - - return $filters; - } - - public function getFunctions() - { - return array( - new Twig_SimpleFunction('max', 'max'), - new Twig_SimpleFunction('min', 'min'), - new Twig_SimpleFunction('range', 'range'), - new Twig_SimpleFunction('constant', 'twig_constant'), - new Twig_SimpleFunction('cycle', 'twig_cycle'), - new Twig_SimpleFunction('random', 'twig_random', array('needs_environment' => true)), - new Twig_SimpleFunction('date', 'twig_date_converter', array('needs_environment' => true)), - new Twig_SimpleFunction('include', 'twig_include', array('needs_environment' => true, 'needs_context' => true, 'is_safe' => array('all'))), - new Twig_SimpleFunction('source', 'twig_source', array('needs_environment' => true, 'is_safe' => array('all'))), - ); - } - - public function getTests() - { - return array( - new Twig_SimpleTest('even', null, array('node_class' => 'Twig_Node_Expression_Test_Even')), - new Twig_SimpleTest('odd', null, array('node_class' => 'Twig_Node_Expression_Test_Odd')), - new Twig_SimpleTest('defined', null, array('node_class' => 'Twig_Node_Expression_Test_Defined')), - new Twig_SimpleTest('sameas', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas', 'deprecated' => '1.21', 'alternative' => 'same as')), - new Twig_SimpleTest('same as', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas')), - new Twig_SimpleTest('none', null, array('node_class' => 'Twig_Node_Expression_Test_Null')), - new Twig_SimpleTest('null', null, array('node_class' => 'Twig_Node_Expression_Test_Null')), - new Twig_SimpleTest('divisibleby', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby', 'deprecated' => '1.21', 'alternative' => 'divisible by')), - new Twig_SimpleTest('divisible by', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby')), - new Twig_SimpleTest('constant', null, array('node_class' => 'Twig_Node_Expression_Test_Constant')), - new Twig_SimpleTest('empty', 'twig_test_empty'), - new Twig_SimpleTest('iterable', 'twig_test_iterable'), - ); - } - - public function getOperators() - { - return array( - array( - 'not' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'), - '-' => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Neg'), - '+' => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Pos'), - ), - array( - 'or' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'and' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'b-or' => array('precedence' => 16, 'class' => 'Twig_Node_Expression_Binary_BitwiseOr', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'b-xor' => array('precedence' => 17, 'class' => 'Twig_Node_Expression_Binary_BitwiseXor', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'b-and' => array('precedence' => 18, 'class' => 'Twig_Node_Expression_Binary_BitwiseAnd', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '==' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '!=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '<' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '>' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '>=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '<=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'not in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotIn', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_In', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'matches' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Matches', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'starts with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_StartsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'ends with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_EndsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '..' => array('precedence' => 25, 'class' => 'Twig_Node_Expression_Binary_Range', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '+' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Add', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '-' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Sub', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '~' => array('precedence' => 40, 'class' => 'Twig_Node_Expression_Binary_Concat', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '*' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mul', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '/' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Div', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '//' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_FloorDiv', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '%' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'is' => array('precedence' => 100, 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'is not' => array('precedence' => 100, 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '**' => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT), - '??' => array('precedence' => 300, 'class' => 'Twig_Node_Expression_NullCoalesce', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT), - ), - ); - } - - public function getName() - { - return 'core'; - } -} - -/** - * Cycles over a value. - * - * @param ArrayAccess|array $values - * @param int $position The cycle position - * - * @return string The next value in the cycle - */ -function twig_cycle($values, $position) -{ - if (!is_array($values) && !$values instanceof ArrayAccess) { - return $values; - } - - return $values[$position % count($values)]; -} - -/** - * Returns a random value depending on the supplied parameter type: - * - a random item from a Traversable or array - * - a random character from a string - * - a random integer between 0 and the integer parameter. - * - * @param Twig_Environment $env - * @param Traversable|array|int|float|string $values The values to pick a random item from - * - * @throws Twig_Error_Runtime when $values is an empty array (does not apply to an empty string which is returned as is) - * - * @return mixed A random value from the given sequence - */ -function twig_random(Twig_Environment $env, $values = null) -{ - if (null === $values) { - return mt_rand(); - } - - if (is_int($values) || is_float($values)) { - return $values < 0 ? mt_rand($values, 0) : mt_rand(0, $values); - } - - if ($values instanceof Traversable) { - $values = iterator_to_array($values); - } elseif (is_string($values)) { - if ('' === $values) { - return ''; - } - if (null !== $charset = $env->getCharset()) { - if ('UTF-8' !== $charset) { - $values = twig_convert_encoding($values, 'UTF-8', $charset); - } - - // unicode version of str_split() - // split at all positions, but not after the start and not before the end - $values = preg_split('/(? $value) { - $values[$i] = twig_convert_encoding($value, $charset, 'UTF-8'); - } - } - } else { - return $values[mt_rand(0, strlen($values) - 1)]; - } - } - - if (!is_array($values)) { - return $values; - } - - if (0 === count($values)) { - throw new Twig_Error_Runtime('The random function cannot pick from an empty array.'); - } - - return $values[array_rand($values, 1)]; -} - -/** - * Converts a date to the given format. - * - *
- *   {{ post.published_at|date("m/d/Y") }}
- * 
- * - * @param Twig_Environment $env - * @param DateTime|DateTimeInterface|DateInterval|string $date A date - * @param string|null $format The target format, null to use the default - * @param DateTimeZone|string|null|false $timezone The target timezone, null to use the default, false to leave unchanged - * - * @return string The formatted date - */ -function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $timezone = null) -{ - if (null === $format) { - $formats = $env->getExtension('Twig_Extension_Core')->getDateFormat(); - $format = $date instanceof DateInterval ? $formats[1] : $formats[0]; - } - - if ($date instanceof DateInterval) { - return $date->format($format); - } - - return twig_date_converter($env, $date, $timezone)->format($format); -} - -/** - * Returns a new date object modified. - * - *
- *   {{ post.published_at|date_modify("-1day")|date("m/d/Y") }}
- * 
- * - * @param Twig_Environment $env - * @param DateTime|string $date A date - * @param string $modifier A modifier string - * - * @return DateTime A new date object - */ -function twig_date_modify_filter(Twig_Environment $env, $date, $modifier) -{ - $date = twig_date_converter($env, $date, false); - $resultDate = $date->modify($modifier); - - // This is a hack to ensure PHP 5.2 support and support for DateTimeImmutable - // DateTime::modify does not return the modified DateTime object < 5.3.0 - // and DateTimeImmutable does not modify $date. - return null === $resultDate ? $date : $resultDate; -} - -/** - * Converts an input to a DateTime instance. - * - *
- *    {% if date(user.created_at) < date('+2days') %}
- *      {# do something #}
- *    {% endif %}
- * 
- * - * @param Twig_Environment $env - * @param DateTime|DateTimeInterface|string|null $date A date - * @param DateTimeZone|string|null|false $timezone The target timezone, null to use the default, false to leave unchanged - * - * @return DateTime A DateTime instance - */ -function twig_date_converter(Twig_Environment $env, $date = null, $timezone = null) -{ - // determine the timezone - if (false !== $timezone) { - if (null === $timezone) { - $timezone = $env->getExtension('Twig_Extension_Core')->getTimezone(); - } elseif (!$timezone instanceof DateTimeZone) { - $timezone = new DateTimeZone($timezone); - } - } - - // immutable dates - if ($date instanceof DateTimeImmutable) { - return false !== $timezone ? $date->setTimezone($timezone) : $date; - } - - if ($date instanceof DateTime || $date instanceof DateTimeInterface) { - $date = clone $date; - if (false !== $timezone) { - $date->setTimezone($timezone); - } - - return $date; - } - - if (null === $date || 'now' === $date) { - return new DateTime($date, false !== $timezone ? $timezone : $env->getExtension('Twig_Extension_Core')->getTimezone()); - } - - $asString = (string) $date; - if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) { - $date = new DateTime('@'.$date); - } else { - $date = new DateTime($date, $env->getExtension('Twig_Extension_Core')->getTimezone()); - } - - if (false !== $timezone) { - $date->setTimezone($timezone); - } - - return $date; -} - -/** - * Replaces strings within a string. - * - * @param string $str String to replace in - * @param array|Traversable $from Replace values - * @param string|null $to Replace to, deprecated (@see http://php.net/manual/en/function.strtr.php) - * - * @return string - */ -function twig_replace_filter($str, $from, $to = null) -{ - if ($from instanceof Traversable) { - $from = iterator_to_array($from); - } elseif (is_string($from) && is_string($to)) { - @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); - - return strtr($str, $from, $to); - } elseif (!is_array($from)) { - throw new Twig_Error_Runtime(sprintf('The "replace" filter expects an array or "Traversable" as replace values, got "%s".', is_object($from) ? get_class($from) : gettype($from))); - } - - return strtr($str, $from); -} - -/** - * Rounds a number. - * - * @param int|float $value The value to round - * @param int|float $precision The rounding precision - * @param string $method The method to use for rounding - * - * @return int|float The rounded number - */ -function twig_round($value, $precision = 0, $method = 'common') -{ - if ('common' == $method) { - return round($value, $precision); - } - - if ('ceil' != $method && 'floor' != $method) { - throw new Twig_Error_Runtime('The round filter only supports the "common", "ceil", and "floor" methods.'); - } - - return $method($value * pow(10, $precision)) / pow(10, $precision); -} - -/** - * Number format filter. - * - * All of the formatting options can be left null, in that case the defaults will - * be used. Supplying any of the parameters will override the defaults set in the - * environment object. - * - * @param Twig_Environment $env - * @param mixed $number A float/int/string of the number to format - * @param int $decimal the number of decimal points to display - * @param string $decimalPoint the character(s) to use for the decimal point - * @param string $thousandSep the character(s) to use for the thousands separator - * - * @return string The formatted number - */ -function twig_number_format_filter(Twig_Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null) -{ - $defaults = $env->getExtension('Twig_Extension_Core')->getNumberFormat(); - if (null === $decimal) { - $decimal = $defaults[0]; - } - - if (null === $decimalPoint) { - $decimalPoint = $defaults[1]; - } - - if (null === $thousandSep) { - $thousandSep = $defaults[2]; - } - - return number_format((float) $number, $decimal, $decimalPoint, $thousandSep); -} - -/** - * URL encodes (RFC 3986) a string as a path segment or an array as a query string. - * - * @param string|array $url A URL or an array of query parameters - * - * @return string The URL encoded value - */ -function twig_urlencode_filter($url) -{ - if (is_array($url)) { - if (defined('PHP_QUERY_RFC3986')) { - return http_build_query($url, '', '&', PHP_QUERY_RFC3986); - } - - return http_build_query($url, '', '&'); - } - - return rawurlencode($url); -} - -if (PHP_VERSION_ID < 50300) { - /** - * JSON encodes a variable. - * - * @param mixed $value the value to encode - * @param int $options Not used on PHP 5.2.x - * - * @return mixed The JSON encoded value - */ - function twig_jsonencode_filter($value, $options = 0) - { - if ($value instanceof Twig_Markup) { - $value = (string) $value; - } elseif (is_array($value)) { - array_walk_recursive($value, '_twig_markup2string'); - } - - return json_encode($value); - } -} else { - /** - * JSON encodes a variable. - * - * @param mixed $value the value to encode - * @param int $options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT - * - * @return mixed The JSON encoded value - */ - function twig_jsonencode_filter($value, $options = 0) - { - if ($value instanceof Twig_Markup) { - $value = (string) $value; - } elseif (is_array($value)) { - array_walk_recursive($value, '_twig_markup2string'); - } - - return json_encode($value, $options); - } -} - -function _twig_markup2string(&$value) -{ - if ($value instanceof Twig_Markup) { - $value = (string) $value; - } -} - -/** - * Merges an array with another one. - * - *
- *  {% set items = { 'apple': 'fruit', 'orange': 'fruit' } %}
- *
- *  {% set items = items|merge({ 'peugeot': 'car' }) %}
- *
- *  {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #}
- * 
- * - * @param array|Traversable $arr1 An array - * @param array|Traversable $arr2 An array - * - * @return array The merged array - */ -function twig_array_merge($arr1, $arr2) -{ - if ($arr1 instanceof Traversable) { - $arr1 = iterator_to_array($arr1); - } elseif (!is_array($arr1)) { - throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as first argument.', gettype($arr1))); - } - - if ($arr2 instanceof Traversable) { - $arr2 = iterator_to_array($arr2); - } elseif (!is_array($arr2)) { - throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as second argument.', gettype($arr2))); - } - - return array_merge($arr1, $arr2); -} - -/** - * Slices a variable. - * - * @param Twig_Environment $env - * @param mixed $item A variable - * @param int $start Start of the slice - * @param int $length Size of the slice - * @param bool $preserveKeys Whether to preserve key or not (when the input is an array) - * - * @return mixed The sliced variable - */ -function twig_slice(Twig_Environment $env, $item, $start, $length = null, $preserveKeys = false) -{ - if ($item instanceof Traversable) { - while ($item instanceof IteratorAggregate) { - $item = $item->getIterator(); - } - - if ($start >= 0 && $length >= 0 && $item instanceof Iterator) { - try { - return iterator_to_array(new LimitIterator($item, $start, $length === null ? -1 : $length), $preserveKeys); - } catch (OutOfBoundsException $exception) { - return array(); - } - } - - $item = iterator_to_array($item, $preserveKeys); - } - - if (is_array($item)) { - return array_slice($item, $start, $length, $preserveKeys); - } - - $item = (string) $item; - - if (function_exists('mb_get_info') && null !== $charset = $env->getCharset()) { - return (string) mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset); - } - - return (string) (null === $length ? substr($item, $start) : substr($item, $start, $length)); -} - -/** - * Returns the first element of the item. - * - * @param Twig_Environment $env - * @param mixed $item A variable - * - * @return mixed The first element of the item - */ -function twig_first(Twig_Environment $env, $item) -{ - $elements = twig_slice($env, $item, 0, 1, false); - - return is_string($elements) ? $elements : current($elements); -} - -/** - * Returns the last element of the item. - * - * @param Twig_Environment $env - * @param mixed $item A variable - * - * @return mixed The last element of the item - */ -function twig_last(Twig_Environment $env, $item) -{ - $elements = twig_slice($env, $item, -1, 1, false); - - return is_string($elements) ? $elements : current($elements); -} - -/** - * Joins the values to a string. - * - * The separator between elements is an empty string per default, you can define it with the optional parameter. - * - *
- *  {{ [1, 2, 3]|join('|') }}
- *  {# returns 1|2|3 #}
- *
- *  {{ [1, 2, 3]|join }}
- *  {# returns 123 #}
- * 
- * - * @param array $value An array - * @param string $glue The separator - * - * @return string The concatenated string - */ -function twig_join_filter($value, $glue = '') -{ - if ($value instanceof Traversable) { - $value = iterator_to_array($value, false); - } - - return implode($glue, (array) $value); -} - -/** - * Splits the string into an array. - * - *
- *  {{ "one,two,three"|split(',') }}
- *  {# returns [one, two, three] #}
- *
- *  {{ "one,two,three,four,five"|split(',', 3) }}
- *  {# returns [one, two, "three,four,five"] #}
- *
- *  {{ "123"|split('') }}
- *  {# returns [1, 2, 3] #}
- *
- *  {{ "aabbcc"|split('', 2) }}
- *  {# returns [aa, bb, cc] #}
- * 
- * - * @param Twig_Environment $env - * @param string $value A string - * @param string $delimiter The delimiter - * @param int $limit The limit - * - * @return array The split string as an array - */ -function twig_split_filter(Twig_Environment $env, $value, $delimiter, $limit = null) -{ - if (!empty($delimiter)) { - return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit); - } - - if (!function_exists('mb_get_info') || null === $charset = $env->getCharset()) { - return str_split($value, null === $limit ? 1 : $limit); - } - - if ($limit <= 1) { - return preg_split('/(? - * {% for key in array|keys %} - * {# ... #} - * {% endfor %} - * - * - * @param array $array An array - * - * @return array The keys - */ -function twig_get_array_keys_filter($array) -{ - if ($array instanceof Traversable) { - while ($array instanceof IteratorAggregate) { - $array = $array->getIterator(); - } - - if ($array instanceof Iterator) { - $keys = array(); - $array->rewind(); - while ($array->valid()) { - $keys[] = $array->key(); - $array->next(); - } - - return $keys; - } - - $keys = array(); - foreach ($array as $key => $item) { - $keys[] = $key; - } - - return $keys; - } - - if (!is_array($array)) { - return array(); - } - - return array_keys($array); -} - -/** - * Reverses a variable. - * - * @param Twig_Environment $env - * @param array|Traversable|string $item An array, a Traversable instance, or a string - * @param bool $preserveKeys Whether to preserve key or not - * - * @return mixed The reversed input - */ -function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false) -{ - if ($item instanceof Traversable) { - return array_reverse(iterator_to_array($item), $preserveKeys); - } - - if (is_array($item)) { - return array_reverse($item, $preserveKeys); - } - - if (null !== $charset = $env->getCharset()) { - $string = (string) $item; - - if ('UTF-8' !== $charset) { - $item = twig_convert_encoding($string, 'UTF-8', $charset); - } - - preg_match_all('/./us', $item, $matches); - - $string = implode('', array_reverse($matches[0])); - - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, $charset, 'UTF-8'); - } - - return $string; - } - - return strrev((string) $item); -} - -/** - * Sorts an array. - * - * @param array|Traversable $array - * - * @return array - */ -function twig_sort_filter($array) -{ - if ($array instanceof Traversable) { - $array = iterator_to_array($array); - } elseif (!is_array($array)) { - throw new Twig_Error_Runtime(sprintf('The sort filter only works with arrays or "Traversable", got "%s".', gettype($array))); - } - - asort($array); - - return $array; -} - -/** - * @internal - */ -function twig_in_filter($value, $compare) -{ - if (is_array($compare)) { - return in_array($value, $compare, is_object($value) || is_resource($value)); - } elseif (is_string($compare) && (is_string($value) || is_int($value) || is_float($value))) { - return '' === $value || false !== strpos($compare, (string) $value); - } elseif ($compare instanceof Traversable) { - if (is_object($value) || is_resource($value)) { - foreach ($compare as $item) { - if ($item === $value) { - return true; - } - } - } else { - foreach ($compare as $item) { - if ($item == $value) { - return true; - } - } - } - - return false; - } - - return false; -} - -/** - * Returns a trimmed string. - * - * @return string - * - * @throws Twig_Error_Runtime When an invalid trimming side is used (not a string or not 'left', 'right', or 'both') - */ -function twig_trim_filter($string, $characterMask = null, $side = 'both') -{ - if (null === $characterMask) { - $characterMask = " \t\n\r\0\x0B"; - } - - switch ($side) { - case 'both': - return trim($string, $characterMask); - case 'left': - return ltrim($string, $characterMask); - case 'right': - return rtrim($string, $characterMask); - default: - throw new Twig_Error_Runtime('Trimming side must be "left", "right" or "both".'); - } -} - -/** - * Escapes a string. - * - * @param Twig_Environment $env - * @param mixed $string The value to be escaped - * @param string $strategy The escaping strategy - * @param string $charset The charset - * @param bool $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false) - * - * @return string - */ -function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false) -{ - if ($autoescape && $string instanceof Twig_Markup) { - return $string; - } - - if (!is_string($string)) { - if (is_object($string) && method_exists($string, '__toString')) { - $string = (string) $string; - } elseif (in_array($strategy, array('html', 'js', 'css', 'html_attr', 'url'))) { - return $string; - } - } - - if (null === $charset) { - $charset = $env->getCharset(); - } - - switch ($strategy) { - case 'html': - // see http://php.net/htmlspecialchars - - // Using a static variable to avoid initializing the array - // each time the function is called. Moving the declaration on the - // top of the function slow downs other escaping strategies. - static $htmlspecialcharsCharsets = array( - 'ISO-8859-1' => true, 'ISO8859-1' => true, - 'ISO-8859-15' => true, 'ISO8859-15' => true, - 'utf-8' => true, 'UTF-8' => true, - 'CP866' => true, 'IBM866' => true, '866' => true, - 'CP1251' => true, 'WINDOWS-1251' => true, 'WIN-1251' => true, - '1251' => true, - 'CP1252' => true, 'WINDOWS-1252' => true, '1252' => true, - 'KOI8-R' => true, 'KOI8-RU' => true, 'KOI8R' => true, - 'BIG5' => true, '950' => true, - 'GB2312' => true, '936' => true, - 'BIG5-HKSCS' => true, - 'SHIFT_JIS' => true, 'SJIS' => true, '932' => true, - 'EUC-JP' => true, 'EUCJP' => true, - 'ISO8859-5' => true, 'ISO-8859-5' => true, 'MACROMAN' => true, - ); - - if (isset($htmlspecialcharsCharsets[$charset])) { - return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset); - } - - if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) { - // cache the lowercase variant for future iterations - $htmlspecialcharsCharsets[$charset] = true; - - return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset); - } - - $string = twig_convert_encoding($string, 'UTF-8', $charset); - $string = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); - - return twig_convert_encoding($string, $charset, 'UTF-8'); - - case 'js': - // escape all non-alphanumeric characters - // into their \xHH or \uHHHH representations - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, 'UTF-8', $charset); - } - - if (0 == strlen($string) ? false : 1 !== preg_match('/^./su', $string)) { - throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.'); - } - - $string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', '_twig_escape_js_callback', $string); - - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, $charset, 'UTF-8'); - } - - return $string; - - case 'css': - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, 'UTF-8', $charset); - } - - if (0 == strlen($string) ? false : 1 !== preg_match('/^./su', $string)) { - throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.'); - } - - $string = preg_replace_callback('#[^a-zA-Z0-9]#Su', '_twig_escape_css_callback', $string); - - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, $charset, 'UTF-8'); - } - - return $string; - - case 'html_attr': - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, 'UTF-8', $charset); - } - - if (0 == strlen($string) ? false : 1 !== preg_match('/^./su', $string)) { - throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.'); - } - - $string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', '_twig_escape_html_attr_callback', $string); - - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, $charset, 'UTF-8'); - } - - return $string; - - case 'url': - if (PHP_VERSION_ID < 50300) { - return str_replace('%7E', '~', rawurlencode($string)); - } - - return rawurlencode($string); - - default: - static $escapers; - - if (null === $escapers) { - $escapers = $env->getExtension('Twig_Extension_Core')->getEscapers(); - } - - if (isset($escapers[$strategy])) { - return call_user_func($escapers[$strategy], $env, $string, $charset); - } - - $validStrategies = implode(', ', array_merge(array('html', 'js', 'url', 'css', 'html_attr'), array_keys($escapers))); - - throw new Twig_Error_Runtime(sprintf('Invalid escaping strategy "%s" (valid ones: %s).', $strategy, $validStrategies)); - } -} - -/** - * @internal - */ -function twig_escape_filter_is_safe(Twig_Node $filterArgs) -{ - foreach ($filterArgs as $arg) { - if ($arg instanceof Twig_Node_Expression_Constant) { - return array($arg->getAttribute('value')); - } - - return array(); - } - - return array('html'); -} - -if (function_exists('mb_convert_encoding')) { - function twig_convert_encoding($string, $to, $from) - { - return mb_convert_encoding($string, $to, $from); - } -} elseif (function_exists('iconv')) { - function twig_convert_encoding($string, $to, $from) - { - return iconv($from, $to, $string); - } -} else { - function twig_convert_encoding($string, $to, $from) - { - throw new Twig_Error_Runtime('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).'); - } -} - -function _twig_escape_js_callback($matches) -{ - $char = $matches[0]; - - // \xHH - if (!isset($char[1])) { - return '\\x'.strtoupper(substr('00'.bin2hex($char), -2)); - } - - // \uHHHH - $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8'); - $char = strtoupper(bin2hex($char)); - - if (4 >= strlen($char)) { - return sprintf('\u%04s', $char); - } - - return sprintf('\u%04s\u%04s', substr($char, 0, -4), substr($char, -4)); -} - -function _twig_escape_css_callback($matches) -{ - $char = $matches[0]; - - // \xHH - if (!isset($char[1])) { - $hex = ltrim(strtoupper(bin2hex($char)), '0'); - if (0 === strlen($hex)) { - $hex = '0'; - } - - return '\\'.$hex.' '; - } - - // \uHHHH - $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8'); - - return '\\'.ltrim(strtoupper(bin2hex($char)), '0').' '; -} - -/** - * This function is adapted from code coming from Zend Framework. - * - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ -function _twig_escape_html_attr_callback($matches) -{ - /* - * While HTML supports far more named entities, the lowest common denominator - * has become HTML5's XML Serialisation which is restricted to the those named - * entities that XML supports. Using HTML entities would result in this error: - * XML Parsing Error: undefined entity - */ - static $entityMap = array( - 34 => 'quot', /* quotation mark */ - 38 => 'amp', /* ampersand */ - 60 => 'lt', /* less-than sign */ - 62 => 'gt', /* greater-than sign */ - ); - - $chr = $matches[0]; - $ord = ord($chr); - - /* - * The following replaces characters undefined in HTML with the - * hex entity for the Unicode replacement character. - */ - if (($ord <= 0x1f && $chr != "\t" && $chr != "\n" && $chr != "\r") || ($ord >= 0x7f && $ord <= 0x9f)) { - return '�'; - } - - /* - * Check if the current character to escape has a name entity we should - * replace it with while grabbing the hex value of the character. - */ - if (strlen($chr) == 1) { - $hex = strtoupper(substr('00'.bin2hex($chr), -2)); - } else { - $chr = twig_convert_encoding($chr, 'UTF-16BE', 'UTF-8'); - $hex = strtoupper(substr('0000'.bin2hex($chr), -4)); - } - - $int = hexdec($hex); - if (array_key_exists($int, $entityMap)) { - return sprintf('&%s;', $entityMap[$int]); - } - - /* - * Per OWASP recommendations, we'll use hex entities for any other - * characters where a named entity does not exist. - */ - return sprintf('&#x%s;', $hex); -} - -// add multibyte extensions if possible -if (function_exists('mb_get_info')) { - /** - * Returns the length of a variable. - * - * @param Twig_Environment $env - * @param mixed $thing A variable - * - * @return int The length of the value - */ - function twig_length_filter(Twig_Environment $env, $thing) - { - if (null === $thing) { - return 0; - } - - if (is_scalar($thing)) { - return mb_strlen($thing, $env->getCharset()); - } - - if (is_object($thing) && method_exists($thing, '__toString') && !$thing instanceof \Countable) { - return mb_strlen((string) $thing, $env->getCharset()); - } - - if ($thing instanceof \Countable || is_array($thing)) { - return count($thing); - } - - return 1; - } - - /** - * Converts a string to uppercase. - * - * @param Twig_Environment $env - * @param string $string A string - * - * @return string The uppercased string - */ - function twig_upper_filter(Twig_Environment $env, $string) - { - if (null !== $charset = $env->getCharset()) { - return mb_strtoupper($string, $charset); - } - - return strtoupper($string); - } - - /** - * Converts a string to lowercase. - * - * @param Twig_Environment $env - * @param string $string A string - * - * @return string The lowercased string - */ - function twig_lower_filter(Twig_Environment $env, $string) - { - if (null !== $charset = $env->getCharset()) { - return mb_strtolower($string, $charset); - } - - return strtolower($string); - } - - /** - * Returns a titlecased string. - * - * @param Twig_Environment $env - * @param string $string A string - * - * @return string The titlecased string - */ - function twig_title_string_filter(Twig_Environment $env, $string) - { - if (null !== $charset = $env->getCharset()) { - return mb_convert_case($string, MB_CASE_TITLE, $charset); - } - - return ucwords(strtolower($string)); - } - - /** - * Returns a capitalized string. - * - * @param Twig_Environment $env - * @param string $string A string - * - * @return string The capitalized string - */ - function twig_capitalize_string_filter(Twig_Environment $env, $string) - { - if (null !== $charset = $env->getCharset()) { - return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset).mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset); - } - - return ucfirst(strtolower($string)); - } -} -// and byte fallback -else { - /** - * Returns the length of a variable. - * - * @param Twig_Environment $env - * @param mixed $thing A variable - * - * @return int The length of the value - */ - function twig_length_filter(Twig_Environment $env, $thing) - { - if (null === $thing) { - return 0; - } - - if (is_scalar($thing)) { - return strlen($thing); - } - - if (is_object($thing) && method_exists($thing, '__toString') && !$thing instanceof \Countable) { - return strlen((string) $thing); - } - - if ($thing instanceof \Countable || is_array($thing)) { - return count($thing); - } - - return 1; - } - - /** - * Returns a titlecased string. - * - * @param Twig_Environment $env - * @param string $string A string - * - * @return string The titlecased string - */ - function twig_title_string_filter(Twig_Environment $env, $string) - { - return ucwords(strtolower($string)); - } - - /** - * Returns a capitalized string. - * - * @param Twig_Environment $env - * @param string $string A string - * - * @return string The capitalized string - */ - function twig_capitalize_string_filter(Twig_Environment $env, $string) - { - return ucfirst(strtolower($string)); - } -} - -/** - * @internal - */ -function twig_ensure_traversable($seq) -{ - if ($seq instanceof Traversable || is_array($seq)) { - return $seq; - } - - return array(); -} - -/** - * Checks if a variable is empty. - * - *
- * {# evaluates to true if the foo variable is null, false, or the empty string #}
- * {% if foo is empty %}
- *     {# ... #}
- * {% endif %}
- * 
- * - * @param mixed $value A variable - * - * @return bool true if the value is empty, false otherwise - */ -function twig_test_empty($value) -{ - if ($value instanceof Countable) { - return 0 == count($value); - } - - if (is_object($value) && method_exists($value, '__toString')) { - return '' === (string) $value; - } - - return '' === $value || false === $value || null === $value || array() === $value; -} - -/** - * Checks if a variable is traversable. - * - *
- * {# evaluates to true if the foo variable is an array or a traversable object #}
- * {% if foo is traversable %}
- *     {# ... #}
- * {% endif %}
- * 
- * - * @param mixed $value A variable - * - * @return bool true if the value is traversable - */ -function twig_test_iterable($value) -{ - return $value instanceof Traversable || is_array($value); -} - -/** - * Renders a template. - * - * @param Twig_Environment $env - * @param array $context - * @param string|array $template The template to render or an array of templates to try consecutively - * @param array $variables The variables to pass to the template - * @param bool $withContext - * @param bool $ignoreMissing Whether to ignore missing templates or not - * @param bool $sandboxed Whether to sandbox the template or not - * - * @return string The rendered template - */ -function twig_include(Twig_Environment $env, $context, $template, $variables = array(), $withContext = true, $ignoreMissing = false, $sandboxed = false) -{ - $alreadySandboxed = false; - $sandbox = null; - if ($withContext) { - $variables = array_merge($context, $variables); - } - - if ($isSandboxed = $sandboxed && $env->hasExtension('Twig_Extension_Sandbox')) { - $sandbox = $env->getExtension('Twig_Extension_Sandbox'); - if (!$alreadySandboxed = $sandbox->isSandboxed()) { - $sandbox->enableSandbox(); - } - } - - $result = null; - try { - $result = $env->resolveTemplate($template)->render($variables); - } catch (Twig_Error_Loader $e) { - if (!$ignoreMissing) { - if ($isSandboxed && !$alreadySandboxed) { - $sandbox->disableSandbox(); - } - - throw $e; - } - } catch (Throwable $e) { - if ($isSandboxed && !$alreadySandboxed) { - $sandbox->disableSandbox(); - } - - throw $e; - } catch (Exception $e) { - if ($isSandboxed && !$alreadySandboxed) { - $sandbox->disableSandbox(); - } - - throw $e; - } - - if ($isSandboxed && !$alreadySandboxed) { - $sandbox->disableSandbox(); - } - - return $result; -} - -/** - * Returns a template content without rendering it. - * - * @param Twig_Environment $env - * @param string $name The template name - * @param bool $ignoreMissing Whether to ignore missing templates or not - * - * @return string The template source - */ -function twig_source(Twig_Environment $env, $name, $ignoreMissing = false) -{ - $loader = $env->getLoader(); - try { - if (!$loader instanceof Twig_SourceContextLoaderInterface) { - return $loader->getSource($name); - } else { - return $loader->getSourceContext($name)->getCode(); - } - } catch (Twig_Error_Loader $e) { - if (!$ignoreMissing) { - throw $e; - } - } -} - -/** - * Provides the ability to get constants from instances as well as class/global constants. - * - * @param string $constant The name of the constant - * @param null|object $object The object to get the constant from - * - * @return string - */ -function twig_constant($constant, $object = null) -{ - if (null !== $object) { - $constant = get_class($object).'::'.$constant; - } - - return constant($constant); -} - -/** - * Checks if a constant exists. - * - * @param string $constant The name of the constant - * @param null|object $object The object to get the constant from - * - * @return bool - */ -function twig_constant_is_defined($constant, $object = null) -{ - if (null !== $object) { - $constant = get_class($object).'::'.$constant; - } - - return defined($constant); -} - -/** - * Batches item. - * - * @param array $items An array of items - * @param int $size The size of the batch - * @param mixed $fill A value used to fill missing items - * - * @return array - */ -function twig_array_batch($items, $size, $fill = null) -{ - if ($items instanceof Traversable) { - $items = iterator_to_array($items, false); - } - - $size = ceil($size); - - $result = array_chunk($items, $size, true); - - if (null !== $fill && !empty($result)) { - $last = count($result) - 1; - if ($fillCount = $size - count($result[$last])) { - $result[$last] = array_merge( - $result[$last], - array_fill(0, $fillCount, $fill) - ); - } - } - - return $result; -} - -class_alias('Twig_Extension_Core', 'Twig\Extension\CoreExtension', false); diff --git a/system/libs/Twig/Extension/CoreExtension.php b/system/libs/Twig/Extension/CoreExtension.php new file mode 100644 index 00000000..5f3cc24a --- /dev/null +++ b/system/libs/Twig/Extension/CoreExtension.php @@ -0,0 +1,1728 @@ +escapers[$strategy] = $callable; + } + + /** + * Gets all defined escapers. + * + * @return array An array of escapers + */ + public function getEscapers() + { + return $this->escapers; + } + + /** + * Sets the default format to be used by the date filter. + * + * @param string $format The default date format string + * @param string $dateIntervalFormat The default date interval format string + */ + public function setDateFormat($format = null, $dateIntervalFormat = null) + { + if (null !== $format) { + $this->dateFormats[0] = $format; + } + + if (null !== $dateIntervalFormat) { + $this->dateFormats[1] = $dateIntervalFormat; + } + } + + /** + * Gets the default format to be used by the date filter. + * + * @return array The default date format string and the default date interval format string + */ + public function getDateFormat() + { + return $this->dateFormats; + } + + /** + * Sets the default timezone to be used by the date filter. + * + * @param \DateTimeZone|string $timezone The default timezone string or a \DateTimeZone object + */ + public function setTimezone($timezone) + { + $this->timezone = $timezone instanceof \DateTimeZone ? $timezone : new \DateTimeZone($timezone); + } + + /** + * Gets the default timezone to be used by the date filter. + * + * @return \DateTimeZone The default timezone currently in use + */ + public function getTimezone() + { + if (null === $this->timezone) { + $this->timezone = new \DateTimeZone(date_default_timezone_get()); + } + + return $this->timezone; + } + + /** + * Sets the default format to be used by the number_format filter. + * + * @param int $decimal the number of decimal places to use + * @param string $decimalPoint the character(s) to use for the decimal point + * @param string $thousandSep the character(s) to use for the thousands separator + */ + public function setNumberFormat($decimal, $decimalPoint, $thousandSep) + { + $this->numberFormat = [$decimal, $decimalPoint, $thousandSep]; + } + + /** + * Get the default format used by the number_format filter. + * + * @return array The arguments for number_format() + */ + public function getNumberFormat() + { + return $this->numberFormat; + } + + public function getTokenParsers() + { + return [ + new ApplyTokenParser(), + new ForTokenParser(), + new IfTokenParser(), + new ExtendsTokenParser(), + new IncludeTokenParser(), + new BlockTokenParser(), + new UseTokenParser(), + new FilterTokenParser(), + new MacroTokenParser(), + new ImportTokenParser(), + new FromTokenParser(), + new SetTokenParser(), + new SpacelessTokenParser(), + new FlushTokenParser(), + new DoTokenParser(), + new EmbedTokenParser(), + new WithTokenParser(), + new DeprecatedTokenParser(), + ]; + } + + public function getFilters() + { + $filters = [ + // formatting filters + new TwigFilter('date', 'twig_date_format_filter', ['needs_environment' => true]), + new TwigFilter('date_modify', 'twig_date_modify_filter', ['needs_environment' => true]), + new TwigFilter('format', 'sprintf'), + new TwigFilter('replace', 'twig_replace_filter'), + new TwigFilter('number_format', 'twig_number_format_filter', ['needs_environment' => true]), + new TwigFilter('abs', 'abs'), + new TwigFilter('round', 'twig_round'), + + // encoding + new TwigFilter('url_encode', 'twig_urlencode_filter'), + new TwigFilter('json_encode', 'twig_jsonencode_filter'), + new TwigFilter('convert_encoding', 'twig_convert_encoding'), + + // string filters + new TwigFilter('title', 'twig_title_string_filter', ['needs_environment' => true]), + new TwigFilter('capitalize', 'twig_capitalize_string_filter', ['needs_environment' => true]), + new TwigFilter('upper', 'strtoupper'), + new TwigFilter('lower', 'strtolower'), + new TwigFilter('striptags', 'strip_tags'), + new TwigFilter('trim', 'twig_trim_filter'), + new TwigFilter('nl2br', 'nl2br', ['pre_escape' => 'html', 'is_safe' => ['html']]), + new TwigFilter('spaceless', 'twig_spaceless', ['is_safe' => ['html']]), + + // array helpers + new TwigFilter('join', 'twig_join_filter'), + new TwigFilter('split', 'twig_split_filter', ['needs_environment' => true]), + new TwigFilter('sort', 'twig_sort_filter'), + new TwigFilter('merge', 'twig_array_merge'), + new TwigFilter('batch', 'twig_array_batch'), + new TwigFilter('filter', 'twig_array_filter'), + new TwigFilter('map', 'twig_array_map'), + new TwigFilter('reduce', 'twig_array_reduce'), + + // string/array filters + new TwigFilter('reverse', 'twig_reverse_filter', ['needs_environment' => true]), + new TwigFilter('length', 'twig_length_filter', ['needs_environment' => true]), + new TwigFilter('slice', 'twig_slice', ['needs_environment' => true]), + new TwigFilter('first', 'twig_first', ['needs_environment' => true]), + new TwigFilter('last', 'twig_last', ['needs_environment' => true]), + + // iteration and runtime + new TwigFilter('default', '_twig_default_filter', ['node_class' => '\Twig\Node\Expression\Filter\DefaultFilter']), + new TwigFilter('keys', 'twig_get_array_keys_filter'), + + // escaping + new TwigFilter('escape', 'twig_escape_filter', ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']), + new TwigFilter('e', 'twig_escape_filter', ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']), + ]; + + if (\function_exists('mb_get_info')) { + $filters[] = new TwigFilter('upper', 'twig_upper_filter', ['needs_environment' => true]); + $filters[] = new TwigFilter('lower', 'twig_lower_filter', ['needs_environment' => true]); + } + + return $filters; + } + + public function getFunctions() + { + return [ + new TwigFunction('max', 'max'), + new TwigFunction('min', 'min'), + new TwigFunction('range', 'range'), + new TwigFunction('constant', 'twig_constant'), + new TwigFunction('cycle', 'twig_cycle'), + new TwigFunction('random', 'twig_random', ['needs_environment' => true]), + new TwigFunction('date', 'twig_date_converter', ['needs_environment' => true]), + new TwigFunction('include', 'twig_include', ['needs_environment' => true, 'needs_context' => true, 'is_safe' => ['all']]), + new TwigFunction('source', 'twig_source', ['needs_environment' => true, 'is_safe' => ['all']]), + ]; + } + + public function getTests() + { + return [ + new TwigTest('even', null, ['node_class' => '\Twig\Node\Expression\Test\EvenTest']), + new TwigTest('odd', null, ['node_class' => '\Twig\Node\Expression\Test\OddTest']), + new TwigTest('defined', null, ['node_class' => '\Twig\Node\Expression\Test\DefinedTest']), + new TwigTest('sameas', null, ['node_class' => '\Twig\Node\Expression\Test\SameasTest', 'deprecated' => '1.21', 'alternative' => 'same as']), + new TwigTest('same as', null, ['node_class' => '\Twig\Node\Expression\Test\SameasTest']), + new TwigTest('none', null, ['node_class' => '\Twig\Node\Expression\Test\NullTest']), + new TwigTest('null', null, ['node_class' => '\Twig\Node\Expression\Test\NullTest']), + new TwigTest('divisibleby', null, ['node_class' => '\Twig\Node\Expression\Test\DivisiblebyTest', 'deprecated' => '1.21', 'alternative' => 'divisible by']), + new TwigTest('divisible by', null, ['node_class' => '\Twig\Node\Expression\Test\DivisiblebyTest']), + new TwigTest('constant', null, ['node_class' => '\Twig\Node\Expression\Test\ConstantTest']), + new TwigTest('empty', 'twig_test_empty'), + new TwigTest('iterable', 'twig_test_iterable'), + ]; + } + + public function getOperators() + { + return [ + [ + 'not' => ['precedence' => 50, 'class' => '\Twig\Node\Expression\Unary\NotUnary'], + '-' => ['precedence' => 500, 'class' => '\Twig\Node\Expression\Unary\NegUnary'], + '+' => ['precedence' => 500, 'class' => '\Twig\Node\Expression\Unary\PosUnary'], + ], + [ + 'or' => ['precedence' => 10, 'class' => '\Twig\Node\Expression\Binary\OrBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'and' => ['precedence' => 15, 'class' => '\Twig\Node\Expression\Binary\AndBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'b-or' => ['precedence' => 16, 'class' => '\Twig\Node\Expression\Binary\BitwiseOrBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'b-xor' => ['precedence' => 17, 'class' => '\Twig\Node\Expression\Binary\BitwiseXorBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'b-and' => ['precedence' => 18, 'class' => '\Twig\Node\Expression\Binary\BitwiseAndBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '==' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\EqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '!=' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\NotEqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '<' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\LessBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '>' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\GreaterBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '>=' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\GreaterEqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '<=' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\LessEqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'not in' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\NotInBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'in' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\InBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'matches' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\MatchesBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'starts with' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\StartsWithBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'ends with' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\EndsWithBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '..' => ['precedence' => 25, 'class' => '\Twig\Node\Expression\Binary\RangeBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '+' => ['precedence' => 30, 'class' => '\Twig\Node\Expression\Binary\AddBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '-' => ['precedence' => 30, 'class' => '\Twig\Node\Expression\Binary\SubBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '~' => ['precedence' => 40, 'class' => '\Twig\Node\Expression\Binary\ConcatBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '*' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\MulBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '/' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\DivBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '//' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\FloorDivBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '%' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\ModBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'is' => ['precedence' => 100, 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'is not' => ['precedence' => 100, 'associativity' => ExpressionParser::OPERATOR_LEFT], + '**' => ['precedence' => 200, 'class' => '\Twig\Node\Expression\Binary\PowerBinary', 'associativity' => ExpressionParser::OPERATOR_RIGHT], + '??' => ['precedence' => 300, 'class' => '\Twig\Node\Expression\NullCoalesceExpression', 'associativity' => ExpressionParser::OPERATOR_RIGHT], + ], + ]; + } + + public function getName() + { + return 'core'; + } +} + +class_alias('Twig\Extension\CoreExtension', 'Twig_Extension_Core'); +} + +namespace { +use Twig\Environment; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; +use Twig\Loader\SourceContextLoaderInterface; +use Twig\Markup; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Node; + +/** + * Cycles over a value. + * + * @param \ArrayAccess|array $values + * @param int $position The cycle position + * + * @return string The next value in the cycle + */ +function twig_cycle($values, $position) +{ + if (!\is_array($values) && !$values instanceof \ArrayAccess) { + return $values; + } + + return $values[$position % \count($values)]; +} + +/** + * Returns a random value depending on the supplied parameter type: + * - a random item from a \Traversable or array + * - a random character from a string + * - a random integer between 0 and the integer parameter. + * + * @param \Traversable|array|int|float|string $values The values to pick a random item from + * @param int|null $max Maximum value used when $values is an int + * + * @throws RuntimeError when $values is an empty array (does not apply to an empty string which is returned as is) + * + * @return mixed A random value from the given sequence + */ +function twig_random(Environment $env, $values = null, $max = null) +{ + if (null === $values) { + return null === $max ? mt_rand() : mt_rand(0, $max); + } + + if (\is_int($values) || \is_float($values)) { + if (null === $max) { + if ($values < 0) { + $max = 0; + $min = $values; + } else { + $max = $values; + $min = 0; + } + } else { + $min = $values; + $max = $max; + } + + return mt_rand($min, $max); + } + + if (\is_string($values)) { + if ('' === $values) { + return ''; + } + if (null !== $charset = $env->getCharset()) { + if ('UTF-8' !== $charset) { + $values = twig_convert_encoding($values, 'UTF-8', $charset); + } + + // unicode version of str_split() + // split at all positions, but not after the start and not before the end + $values = preg_split('/(? $value) { + $values[$i] = twig_convert_encoding($value, $charset, 'UTF-8'); + } + } + } else { + return $values[mt_rand(0, \strlen($values) - 1)]; + } + } + + if (!twig_test_iterable($values)) { + return $values; + } + + $values = twig_to_array($values); + + if (0 === \count($values)) { + throw new RuntimeError('The random function cannot pick from an empty array.'); + } + + return $values[array_rand($values, 1)]; +} + +/** + * Converts a date to the given format. + * + * {{ post.published_at|date("m/d/Y") }} + * + * @param \DateTime|\DateTimeInterface|\DateInterval|string $date A date + * @param string|null $format The target format, null to use the default + * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged + * + * @return string The formatted date + */ +function twig_date_format_filter(Environment $env, $date, $format = null, $timezone = null) +{ + if (null === $format) { + $formats = $env->getExtension('\Twig\Extension\CoreExtension')->getDateFormat(); + $format = $date instanceof \DateInterval ? $formats[1] : $formats[0]; + } + + if ($date instanceof \DateInterval) { + return $date->format($format); + } + + return twig_date_converter($env, $date, $timezone)->format($format); +} + +/** + * Returns a new date object modified. + * + * {{ post.published_at|date_modify("-1day")|date("m/d/Y") }} + * + * @param \DateTime|string $date A date + * @param string $modifier A modifier string + * + * @return \DateTime + */ +function twig_date_modify_filter(Environment $env, $date, $modifier) +{ + $date = twig_date_converter($env, $date, false); + $resultDate = $date->modify($modifier); + + // This is a hack to ensure PHP 5.2 support and support for \DateTimeImmutable + // \DateTime::modify does not return the modified \DateTime object < 5.3.0 + // and \DateTimeImmutable does not modify $date. + return null === $resultDate ? $date : $resultDate; +} + +/** + * Converts an input to a \DateTime instance. + * + * {% if date(user.created_at) < date('+2days') %} + * {# do something #} + * {% endif %} + * + * @param \DateTime|\DateTimeInterface|string|null $date A date + * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged + * + * @return \DateTime + */ +function twig_date_converter(Environment $env, $date = null, $timezone = null) +{ + // determine the timezone + if (false !== $timezone) { + if (null === $timezone) { + $timezone = $env->getExtension('\Twig\Extension\CoreExtension')->getTimezone(); + } elseif (!$timezone instanceof \DateTimeZone) { + $timezone = new \DateTimeZone($timezone); + } + } + + // immutable dates + if ($date instanceof \DateTimeImmutable) { + return false !== $timezone ? $date->setTimezone($timezone) : $date; + } + + if ($date instanceof \DateTime || $date instanceof \DateTimeInterface) { + $date = clone $date; + if (false !== $timezone) { + $date->setTimezone($timezone); + } + + return $date; + } + + if (null === $date || 'now' === $date) { + return new \DateTime($date, false !== $timezone ? $timezone : $env->getExtension('\Twig\Extension\CoreExtension')->getTimezone()); + } + + $asString = (string) $date; + if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) { + $date = new \DateTime('@'.$date); + } else { + $date = new \DateTime($date, $env->getExtension('\Twig\Extension\CoreExtension')->getTimezone()); + } + + if (false !== $timezone) { + $date->setTimezone($timezone); + } + + return $date; +} + +/** + * Replaces strings within a string. + * + * @param string $str String to replace in + * @param array|\Traversable $from Replace values + * @param string|null $to Replace to, deprecated (@see https://secure.php.net/manual/en/function.strtr.php) + * + * @return string + */ +function twig_replace_filter($str, $from, $to = null) +{ + if (\is_string($from) && \is_string($to)) { + @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); + + return strtr($str, $from, $to); + } + + if (!twig_test_iterable($from)) { + 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))); + } + + return strtr($str, twig_to_array($from)); +} + +/** + * Rounds a number. + * + * @param int|float $value The value to round + * @param int|float $precision The rounding precision + * @param string $method The method to use for rounding + * + * @return int|float The rounded number + */ +function twig_round($value, $precision = 0, $method = 'common') +{ + if ('common' == $method) { + return round($value, $precision); + } + + if ('ceil' != $method && 'floor' != $method) { + throw new RuntimeError('The round filter only supports the "common", "ceil", and "floor" methods.'); + } + + return $method($value * pow(10, $precision)) / pow(10, $precision); +} + +/** + * Number format filter. + * + * All of the formatting options can be left null, in that case the defaults will + * be used. Supplying any of the parameters will override the defaults set in the + * environment object. + * + * @param mixed $number A float/int/string of the number to format + * @param int $decimal the number of decimal points to display + * @param string $decimalPoint the character(s) to use for the decimal point + * @param string $thousandSep the character(s) to use for the thousands separator + * + * @return string The formatted number + */ +function twig_number_format_filter(Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null) +{ + $defaults = $env->getExtension('\Twig\Extension\CoreExtension')->getNumberFormat(); + if (null === $decimal) { + $decimal = $defaults[0]; + } + + if (null === $decimalPoint) { + $decimalPoint = $defaults[1]; + } + + if (null === $thousandSep) { + $thousandSep = $defaults[2]; + } + + return number_format((float) $number, $decimal, $decimalPoint, $thousandSep); +} + +/** + * URL encodes (RFC 3986) a string as a path segment or an array as a query string. + * + * @param string|array $url A URL or an array of query parameters + * + * @return string The URL encoded value + */ +function twig_urlencode_filter($url) +{ + if (\is_array($url)) { + if (\defined('PHP_QUERY_RFC3986')) { + return http_build_query($url, '', '&', PHP_QUERY_RFC3986); + } + + return http_build_query($url, '', '&'); + } + + return rawurlencode($url); +} + +/** + * JSON encodes a variable. + * + * @param mixed $value the value to encode + * @param int $options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT + * + * @return mixed The JSON encoded value + */ +function twig_jsonencode_filter($value, $options = 0) +{ + if ($value instanceof Markup) { + $value = (string) $value; + } elseif (\is_array($value)) { + array_walk_recursive($value, '_twig_markup2string'); + } + + return json_encode($value, $options); +} + +function _twig_markup2string(&$value) +{ + if ($value instanceof Markup) { + $value = (string) $value; + } +} + +/** + * Merges an array with another one. + * + * {% set items = { 'apple': 'fruit', 'orange': 'fruit' } %} + * + * {% set items = items|merge({ 'peugeot': 'car' }) %} + * + * {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #} + * + * @param array|\Traversable $arr1 An array + * @param array|\Traversable $arr2 An array + * + * @return array The merged array + */ +function twig_array_merge($arr1, $arr2) +{ + if (!twig_test_iterable($arr1)) { + throw new RuntimeError(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as first argument.', \gettype($arr1))); + } + + if (!twig_test_iterable($arr2)) { + throw new RuntimeError(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as second argument.', \gettype($arr2))); + } + + return array_merge(twig_to_array($arr1), twig_to_array($arr2)); +} + +/** + * Slices a variable. + * + * @param mixed $item A variable + * @param int $start Start of the slice + * @param int $length Size of the slice + * @param bool $preserveKeys Whether to preserve key or not (when the input is an array) + * + * @return mixed The sliced variable + */ +function twig_slice(Environment $env, $item, $start, $length = null, $preserveKeys = false) +{ + if ($item instanceof \Traversable) { + while ($item instanceof \IteratorAggregate) { + $item = $item->getIterator(); + } + + if ($start >= 0 && $length >= 0 && $item instanceof \Iterator) { + try { + return iterator_to_array(new \LimitIterator($item, $start, null === $length ? -1 : $length), $preserveKeys); + } catch (\OutOfBoundsException $e) { + return []; + } + } + + $item = iterator_to_array($item, $preserveKeys); + } + + if (\is_array($item)) { + return \array_slice($item, $start, $length, $preserveKeys); + } + + $item = (string) $item; + + if (\function_exists('mb_get_info') && null !== $charset = $env->getCharset()) { + return (string) mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset); + } + + return (string) (null === $length ? substr($item, $start) : substr($item, $start, $length)); +} + +/** + * Returns the first element of the item. + * + * @param mixed $item A variable + * + * @return mixed The first element of the item + */ +function twig_first(Environment $env, $item) +{ + $elements = twig_slice($env, $item, 0, 1, false); + + return \is_string($elements) ? $elements : current($elements); +} + +/** + * Returns the last element of the item. + * + * @param mixed $item A variable + * + * @return mixed The last element of the item + */ +function twig_last(Environment $env, $item) +{ + $elements = twig_slice($env, $item, -1, 1, false); + + return \is_string($elements) ? $elements : current($elements); +} + +/** + * Joins the values to a string. + * + * The separators between elements are empty strings per default, you can define them with the optional parameters. + * + * {{ [1, 2, 3]|join(', ', ' and ') }} + * {# returns 1, 2 and 3 #} + * + * {{ [1, 2, 3]|join('|') }} + * {# returns 1|2|3 #} + * + * {{ [1, 2, 3]|join }} + * {# returns 123 #} + * + * @param array $value An array + * @param string $glue The separator + * @param string|null $and The separator for the last pair + * + * @return string The concatenated string + */ +function twig_join_filter($value, $glue = '', $and = null) +{ + if (!twig_test_iterable($value)) { + $value = (array) $value; + } + + $value = twig_to_array($value, false); + + if (0 === \count($value)) { + return ''; + } + + if (null === $and || $and === $glue) { + return implode($glue, $value); + } + + if (1 === \count($value)) { + return $value[0]; + } + + return implode($glue, \array_slice($value, 0, -1)).$and.$value[\count($value) - 1]; +} + +/** + * Splits the string into an array. + * + * {{ "one,two,three"|split(',') }} + * {# returns [one, two, three] #} + * + * {{ "one,two,three,four,five"|split(',', 3) }} + * {# returns [one, two, "three,four,five"] #} + * + * {{ "123"|split('') }} + * {# returns [1, 2, 3] #} + * + * {{ "aabbcc"|split('', 2) }} + * {# returns [aa, bb, cc] #} + * + * @param string $value A string + * @param string $delimiter The delimiter + * @param int $limit The limit + * + * @return array The split string as an array + */ +function twig_split_filter(Environment $env, $value, $delimiter, $limit = null) +{ + if (\strlen($delimiter) > 0) { + return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit); + } + + if (!\function_exists('mb_get_info') || null === $charset = $env->getCharset()) { + return str_split($value, null === $limit ? 1 : $limit); + } + + if ($limit <= 1) { + return preg_split('/(?getIterator(); + } + + if ($array instanceof \Iterator) { + $keys = []; + $array->rewind(); + while ($array->valid()) { + $keys[] = $array->key(); + $array->next(); + } + + return $keys; + } + + $keys = []; + foreach ($array as $key => $item) { + $keys[] = $key; + } + + return $keys; + } + + if (!\is_array($array)) { + return []; + } + + return array_keys($array); +} + +/** + * Reverses a variable. + * + * @param array|\Traversable|string $item An array, a \Traversable instance, or a string + * @param bool $preserveKeys Whether to preserve key or not + * + * @return mixed The reversed input + */ +function twig_reverse_filter(Environment $env, $item, $preserveKeys = false) +{ + if ($item instanceof \Traversable) { + return array_reverse(iterator_to_array($item), $preserveKeys); + } + + if (\is_array($item)) { + return array_reverse($item, $preserveKeys); + } + + if (null !== $charset = $env->getCharset()) { + $string = (string) $item; + + if ('UTF-8' !== $charset) { + $item = twig_convert_encoding($string, 'UTF-8', $charset); + } + + preg_match_all('/./us', $item, $matches); + + $string = implode('', array_reverse($matches[0])); + + if ('UTF-8' !== $charset) { + $string = twig_convert_encoding($string, $charset, 'UTF-8'); + } + + return $string; + } + + return strrev((string) $item); +} + +/** + * Sorts an array. + * + * @param array|\Traversable $array + * + * @return array + */ +function twig_sort_filter($array) +{ + if ($array instanceof \Traversable) { + $array = iterator_to_array($array); + } elseif (!\is_array($array)) { + throw new RuntimeError(sprintf('The sort filter only works with arrays or "Traversable", got "%s".', \gettype($array))); + } + + asort($array); + + return $array; +} + +/** + * @internal + */ +function twig_in_filter($value, $compare) +{ + if ($value instanceof Markup) { + $value = (string) $value; + } + if ($compare instanceof Markup) { + $compare = (string) $compare; + } + + if (\is_array($compare)) { + return \in_array($value, $compare, \is_object($value) || \is_resource($value)); + } elseif (\is_string($compare) && (\is_string($value) || \is_int($value) || \is_float($value))) { + return '' === $value || false !== strpos($compare, (string) $value); + } elseif ($compare instanceof \Traversable) { + if (\is_object($value) || \is_resource($value)) { + foreach ($compare as $item) { + if ($item === $value) { + return true; + } + } + } else { + foreach ($compare as $item) { + if ($item == $value) { + return true; + } + } + } + + return false; + } + + return false; +} + +/** + * Returns a trimmed string. + * + * @return string + * + * @throws RuntimeError When an invalid trimming side is used (not a string or not 'left', 'right', or 'both') + */ +function twig_trim_filter($string, $characterMask = null, $side = 'both') +{ + if (null === $characterMask) { + $characterMask = " \t\n\r\0\x0B"; + } + + switch ($side) { + case 'both': + return trim($string, $characterMask); + case 'left': + return ltrim($string, $characterMask); + case 'right': + return rtrim($string, $characterMask); + default: + throw new RuntimeError('Trimming side must be "left", "right" or "both".'); + } +} + +/** + * Removes whitespaces between HTML tags. + * + * @return string + */ +function twig_spaceless($content) +{ + return trim(preg_replace('/>\s+<', $content)); +} + +/** + * Escapes a string. + * + * @param mixed $string The value to be escaped + * @param string $strategy The escaping strategy + * @param string $charset The charset + * @param bool $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false) + * + * @return string + */ +function twig_escape_filter(Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false) +{ + if ($autoescape && $string instanceof Markup) { + return $string; + } + + if (!\is_string($string)) { + if (\is_object($string) && method_exists($string, '__toString')) { + $string = (string) $string; + } elseif (\in_array($strategy, ['html', 'js', 'css', 'html_attr', 'url'])) { + return $string; + } + } + + if ('' === $string) { + return ''; + } + + if (null === $charset) { + $charset = $env->getCharset(); + } + + switch ($strategy) { + case 'html': + // see https://secure.php.net/htmlspecialchars + + // Using a static variable to avoid initializing the array + // each time the function is called. Moving the declaration on the + // top of the function slow downs other escaping strategies. + static $htmlspecialcharsCharsets = [ + 'ISO-8859-1' => true, 'ISO8859-1' => true, + 'ISO-8859-15' => true, 'ISO8859-15' => true, + 'utf-8' => true, 'UTF-8' => true, + 'CP866' => true, 'IBM866' => true, '866' => true, + 'CP1251' => true, 'WINDOWS-1251' => true, 'WIN-1251' => true, + '1251' => true, + 'CP1252' => true, 'WINDOWS-1252' => true, '1252' => true, + 'KOI8-R' => true, 'KOI8-RU' => true, 'KOI8R' => true, + 'BIG5' => true, '950' => true, + 'GB2312' => true, '936' => true, + 'BIG5-HKSCS' => true, + 'SHIFT_JIS' => true, 'SJIS' => true, '932' => true, + 'EUC-JP' => true, 'EUCJP' => true, + 'ISO8859-5' => true, 'ISO-8859-5' => true, 'MACROMAN' => true, + ]; + + if (isset($htmlspecialcharsCharsets[$charset])) { + return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset); + } + + if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) { + // cache the lowercase variant for future iterations + $htmlspecialcharsCharsets[$charset] = true; + + return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset); + } + + $string = twig_convert_encoding($string, 'UTF-8', $charset); + $string = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); + + return twig_convert_encoding($string, $charset, 'UTF-8'); + + case 'js': + // escape all non-alphanumeric characters + // into their \x or \uHHHH representations + if ('UTF-8' !== $charset) { + $string = twig_convert_encoding($string, 'UTF-8', $charset); + } + + if (!preg_match('//u', $string)) { + throw new RuntimeError('The string to escape is not a valid UTF-8 string.'); + } + + $string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', '_twig_escape_js_callback', $string); + + if ('UTF-8' !== $charset) { + $string = twig_convert_encoding($string, $charset, 'UTF-8'); + } + + return $string; + + case 'css': + if ('UTF-8' !== $charset) { + $string = twig_convert_encoding($string, 'UTF-8', $charset); + } + + if (!preg_match('//u', $string)) { + throw new RuntimeError('The string to escape is not a valid UTF-8 string.'); + } + + $string = preg_replace_callback('#[^a-zA-Z0-9]#Su', '_twig_escape_css_callback', $string); + + if ('UTF-8' !== $charset) { + $string = twig_convert_encoding($string, $charset, 'UTF-8'); + } + + return $string; + + case 'html_attr': + if ('UTF-8' !== $charset) { + $string = twig_convert_encoding($string, 'UTF-8', $charset); + } + + if (!preg_match('//u', $string)) { + throw new RuntimeError('The string to escape is not a valid UTF-8 string.'); + } + + $string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', '_twig_escape_html_attr_callback', $string); + + if ('UTF-8' !== $charset) { + $string = twig_convert_encoding($string, $charset, 'UTF-8'); + } + + return $string; + + case 'url': + return rawurlencode($string); + + default: + static $escapers; + + if (null === $escapers) { + $escapers = $env->getExtension('\Twig\Extension\CoreExtension')->getEscapers(); + } + + if (isset($escapers[$strategy])) { + return \call_user_func($escapers[$strategy], $env, $string, $charset); + } + + $validStrategies = implode(', ', array_merge(['html', 'js', 'url', 'css', 'html_attr'], array_keys($escapers))); + + throw new RuntimeError(sprintf('Invalid escaping strategy "%s" (valid ones: %s).', $strategy, $validStrategies)); + } +} + +/** + * @internal + */ +function twig_escape_filter_is_safe(Node $filterArgs) +{ + foreach ($filterArgs as $arg) { + if ($arg instanceof ConstantExpression) { + return [$arg->getAttribute('value')]; + } + + return []; + } + + return ['html']; +} + +if (\function_exists('mb_convert_encoding')) { + function twig_convert_encoding($string, $to, $from) + { + return mb_convert_encoding($string, $to, $from); + } +} elseif (\function_exists('iconv')) { + function twig_convert_encoding($string, $to, $from) + { + return iconv($from, $to, $string); + } +} else { + function twig_convert_encoding($string, $to, $from) + { + throw new RuntimeError('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).'); + } +} + +if (\function_exists('mb_ord')) { + function twig_ord($string) + { + return mb_ord($string, 'UTF-8'); + } +} else { + function twig_ord($string) + { + $code = ($string = unpack('C*', substr($string, 0, 4))) ? $string[1] : 0; + if (0xF0 <= $code) { + return (($code - 0xF0) << 18) + (($string[2] - 0x80) << 12) + (($string[3] - 0x80) << 6) + $string[4] - 0x80; + } + if (0xE0 <= $code) { + return (($code - 0xE0) << 12) + (($string[2] - 0x80) << 6) + $string[3] - 0x80; + } + if (0xC0 <= $code) { + return (($code - 0xC0) << 6) + $string[2] - 0x80; + } + + return $code; + } +} + +function _twig_escape_js_callback($matches) +{ + $char = $matches[0]; + + /* + * A few characters have short escape sequences in JSON and JavaScript. + * Escape sequences supported only by JavaScript, not JSON, are ommitted. + * \" is also supported but omitted, because the resulting string is not HTML safe. + */ + static $shortMap = [ + '\\' => '\\\\', + '/' => '\\/', + "\x08" => '\b', + "\x0C" => '\f', + "\x0A" => '\n', + "\x0D" => '\r', + "\x09" => '\t', + ]; + + if (isset($shortMap[$char])) { + return $shortMap[$char]; + } + + // \uHHHH + $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8'); + $char = strtoupper(bin2hex($char)); + + if (4 >= \strlen($char)) { + return sprintf('\u%04s', $char); + } + + return sprintf('\u%04s\u%04s', substr($char, 0, -4), substr($char, -4)); +} + +function _twig_escape_css_callback($matches) +{ + $char = $matches[0]; + + return sprintf('\\%X ', 1 === \strlen($char) ? \ord($char) : twig_ord($char)); +} + +/** + * This function is adapted from code coming from Zend Framework. + * + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (https://www.zend.com) + * @license https://framework.zend.com/license/new-bsd New BSD License + */ +function _twig_escape_html_attr_callback($matches) +{ + $chr = $matches[0]; + $ord = \ord($chr); + + /* + * The following replaces characters undefined in HTML with the + * hex entity for the Unicode replacement character. + */ + if (($ord <= 0x1f && "\t" != $chr && "\n" != $chr && "\r" != $chr) || ($ord >= 0x7f && $ord <= 0x9f)) { + return '�'; + } + + /* + * Check if the current character to escape has a name entity we should + * replace it with while grabbing the hex value of the character. + */ + if (1 == \strlen($chr)) { + /* + * While HTML supports far more named entities, the lowest common denominator + * has become HTML5's XML Serialisation which is restricted to the those named + * entities that XML supports. Using HTML entities would result in this error: + * XML Parsing Error: undefined entity + */ + static $entityMap = [ + 34 => '"', /* quotation mark */ + 38 => '&', /* ampersand */ + 60 => '<', /* less-than sign */ + 62 => '>', /* greater-than sign */ + ]; + + if (isset($entityMap[$ord])) { + return $entityMap[$ord]; + } + + return sprintf('&#x%02X;', $ord); + } + + /* + * Per OWASP recommendations, we'll use hex entities for any other + * characters where a named entity does not exist. + */ + return sprintf('&#x%04X;', twig_ord($chr)); +} + +// add multibyte extensions if possible +if (\function_exists('mb_get_info')) { + /** + * Returns the length of a variable. + * + * @param mixed $thing A variable + * + * @return int The length of the value + */ + function twig_length_filter(Environment $env, $thing) + { + if (null === $thing) { + return 0; + } + + if (is_scalar($thing)) { + return mb_strlen($thing, $env->getCharset()); + } + + if ($thing instanceof \Countable || \is_array($thing) || $thing instanceof \SimpleXMLElement) { + return \count($thing); + } + + if ($thing instanceof \Traversable) { + return iterator_count($thing); + } + + if (\is_object($thing) && method_exists($thing, '__toString')) { + return mb_strlen((string) $thing, $env->getCharset()); + } + + return 1; + } + + /** + * Converts a string to uppercase. + * + * @param string $string A string + * + * @return string The uppercased string + */ + function twig_upper_filter(Environment $env, $string) + { + if (null !== $charset = $env->getCharset()) { + return mb_strtoupper($string, $charset); + } + + return strtoupper($string); + } + + /** + * Converts a string to lowercase. + * + * @param string $string A string + * + * @return string The lowercased string + */ + function twig_lower_filter(Environment $env, $string) + { + if (null !== $charset = $env->getCharset()) { + return mb_strtolower($string, $charset); + } + + return strtolower($string); + } + + /** + * Returns a titlecased string. + * + * @param string $string A string + * + * @return string The titlecased string + */ + function twig_title_string_filter(Environment $env, $string) + { + if (null !== $charset = $env->getCharset()) { + return mb_convert_case($string, MB_CASE_TITLE, $charset); + } + + return ucwords(strtolower($string)); + } + + /** + * Returns a capitalized string. + * + * @param string $string A string + * + * @return string The capitalized string + */ + function twig_capitalize_string_filter(Environment $env, $string) + { + if (null !== $charset = $env->getCharset()) { + return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset).mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset); + } + + return ucfirst(strtolower($string)); + } +} +// and byte fallback +else { + /** + * Returns the length of a variable. + * + * @param mixed $thing A variable + * + * @return int The length of the value + */ + function twig_length_filter(Environment $env, $thing) + { + if (null === $thing) { + return 0; + } + + if (is_scalar($thing)) { + return \strlen($thing); + } + + if ($thing instanceof \SimpleXMLElement) { + return \count($thing); + } + + if (\is_object($thing) && method_exists($thing, '__toString') && !$thing instanceof \Countable) { + return \strlen((string) $thing); + } + + if ($thing instanceof \Countable || \is_array($thing)) { + return \count($thing); + } + + if ($thing instanceof \IteratorAggregate) { + return iterator_count($thing); + } + + return 1; + } + + /** + * Returns a titlecased string. + * + * @param string $string A string + * + * @return string The titlecased string + */ + function twig_title_string_filter(Environment $env, $string) + { + return ucwords(strtolower($string)); + } + + /** + * Returns a capitalized string. + * + * @param string $string A string + * + * @return string The capitalized string + */ + function twig_capitalize_string_filter(Environment $env, $string) + { + return ucfirst(strtolower($string)); + } +} + +/** + * @internal + */ +function twig_ensure_traversable($seq) +{ + if ($seq instanceof \Traversable || \is_array($seq)) { + return $seq; + } + + return []; +} + +/** + * @internal + */ +function twig_to_array($seq, $preserveKeys = true) +{ + if ($seq instanceof \Traversable) { + return iterator_to_array($seq, $preserveKeys); + } + + if (!\is_array($seq)) { + return $seq; + } + + return $preserveKeys ? $seq : array_values($seq); +} + +/** + * Checks if a variable is empty. + * + * {# evaluates to true if the foo variable is null, false, or the empty string #} + * {% if foo is empty %} + * {# ... #} + * {% endif %} + * + * @param mixed $value A variable + * + * @return bool true if the value is empty, false otherwise + */ +function twig_test_empty($value) +{ + if ($value instanceof \Countable) { + return 0 == \count($value); + } + + if ($value instanceof \Traversable) { + return !iterator_count($value); + } + + if (\is_object($value) && method_exists($value, '__toString')) { + return '' === (string) $value; + } + + return '' === $value || false === $value || null === $value || [] === $value; +} + +/** + * Checks if a variable is traversable. + * + * {# evaluates to true if the foo variable is an array or a traversable object #} + * {% if foo is iterable %} + * {# ... #} + * {% endif %} + * + * @param mixed $value A variable + * + * @return bool true if the value is traversable + */ +function twig_test_iterable($value) +{ + return $value instanceof \Traversable || \is_array($value); +} + +/** + * Renders a template. + * + * @param array $context + * @param string|array $template The template to render or an array of templates to try consecutively + * @param array $variables The variables to pass to the template + * @param bool $withContext + * @param bool $ignoreMissing Whether to ignore missing templates or not + * @param bool $sandboxed Whether to sandbox the template or not + * + * @return string The rendered template + */ +function twig_include(Environment $env, $context, $template, $variables = [], $withContext = true, $ignoreMissing = false, $sandboxed = false) +{ + $alreadySandboxed = false; + $sandbox = null; + if ($withContext) { + $variables = array_merge($context, $variables); + } + + if ($isSandboxed = $sandboxed && $env->hasExtension('\Twig\Extension\SandboxExtension')) { + $sandbox = $env->getExtension('\Twig\Extension\SandboxExtension'); + if (!$alreadySandboxed = $sandbox->isSandboxed()) { + $sandbox->enableSandbox(); + } + } + + $loaded = null; + try { + $loaded = $env->resolveTemplate($template); + } catch (LoaderError $e) { + if (!$ignoreMissing) { + if ($isSandboxed && !$alreadySandboxed) { + $sandbox->disableSandbox(); + } + + throw $e; + } + } catch (\Throwable $e) { + if ($isSandboxed && !$alreadySandboxed) { + $sandbox->disableSandbox(); + } + + throw $e; + } catch (\Exception $e) { + if ($isSandboxed && !$alreadySandboxed) { + $sandbox->disableSandbox(); + } + + throw $e; + } + + try { + $ret = $loaded ? $loaded->render($variables) : ''; + } catch (\Exception $e) { + if ($isSandboxed && !$alreadySandboxed) { + $sandbox->disableSandbox(); + } + + throw $e; + } + + if ($isSandboxed && !$alreadySandboxed) { + $sandbox->disableSandbox(); + } + + return $ret; +} + +/** + * Returns a template content without rendering it. + * + * @param string $name The template name + * @param bool $ignoreMissing Whether to ignore missing templates or not + * + * @return string The template source + */ +function twig_source(Environment $env, $name, $ignoreMissing = false) +{ + $loader = $env->getLoader(); + try { + if (!$loader instanceof SourceContextLoaderInterface) { + return $loader->getSource($name); + } else { + return $loader->getSourceContext($name)->getCode(); + } + } catch (LoaderError $e) { + if (!$ignoreMissing) { + throw $e; + } + } +} + +/** + * Provides the ability to get constants from instances as well as class/global constants. + * + * @param string $constant The name of the constant + * @param object|null $object The object to get the constant from + * + * @return string + */ +function twig_constant($constant, $object = null) +{ + if (null !== $object) { + $constant = \get_class($object).'::'.$constant; + } + + return \constant($constant); +} + +/** + * Checks if a constant exists. + * + * @param string $constant The name of the constant + * @param object|null $object The object to get the constant from + * + * @return bool + */ +function twig_constant_is_defined($constant, $object = null) +{ + if (null !== $object) { + $constant = \get_class($object).'::'.$constant; + } + + return \defined($constant); +} + +/** + * Batches item. + * + * @param array $items An array of items + * @param int $size The size of the batch + * @param mixed $fill A value used to fill missing items + * + * @return array + */ +function twig_array_batch($items, $size, $fill = null, $preserveKeys = true) +{ + if (!twig_test_iterable($items)) { + throw new RuntimeError(sprintf('The "batch" filter expects an array or "Traversable", got "%s".', \is_object($items) ? \get_class($items) : \gettype($items))); + } + + $size = ceil($size); + + $result = array_chunk(twig_to_array($items, $preserveKeys), $size, $preserveKeys); + + if (null !== $fill && $result) { + $last = \count($result) - 1; + if ($fillCount = $size - \count($result[$last])) { + for ($i = 0; $i < $fillCount; ++$i) { + $result[$last][] = $fill; + } + } + } + + return $result; +} + +function twig_array_filter($array, $arrow) +{ + if (\is_array($array)) { + if (\PHP_VERSION_ID >= 50600) { + return array_filter($array, $arrow, \ARRAY_FILTER_USE_BOTH); + } + + return array_filter($array, $arrow); + } + + // the IteratorIterator wrapping is needed as some internal PHP classes are \Traversable but do not implement \Iterator + return new \CallbackFilterIterator(new \IteratorIterator($array), $arrow); +} + +function twig_array_map($array, $arrow) +{ + $r = []; + foreach ($array as $k => $v) { + $r[$k] = $arrow($v, $k); + } + + return $r; +} + +function twig_array_reduce($array, $arrow, $initial = null) +{ + if (!\is_array($array)) { + $array = iterator_to_array($array); + } + + return array_reduce($array, $arrow, $initial); +} +} diff --git a/system/libs/Twig/Extension/Debug.php b/system/libs/Twig/Extension/DebugExtension.php old mode 100755 new mode 100644 similarity index 58% rename from system/libs/Twig/Extension/Debug.php rename to system/libs/Twig/Extension/DebugExtension.php index d0cd1962..09b0223e --- a/system/libs/Twig/Extension/Debug.php +++ b/system/libs/Twig/Extension/DebugExtension.php @@ -9,26 +9,29 @@ * file that was distributed with this source code. */ +namespace Twig\Extension { +use Twig\TwigFunction; + /** * @final */ -class Twig_Extension_Debug extends Twig_Extension +class DebugExtension extends AbstractExtension { public function getFunctions() { // dump is safe if var_dump is overridden by xdebug - $isDumpOutputHtmlSafe = extension_loaded('xdebug') + $isDumpOutputHtmlSafe = \extension_loaded('xdebug') // false means that it was not set (and the default is on) or it explicitly enabled && (false === ini_get('xdebug.overload_var_dump') || ini_get('xdebug.overload_var_dump')) // false means that it was not set (and the default is on) or it explicitly enabled // xdebug.overload_var_dump produces HTML only when html_errors is also enabled && (false === ini_get('html_errors') || ini_get('html_errors')) - || 'cli' === PHP_SAPI + || 'cli' === \PHP_SAPI ; - return array( - new Twig_SimpleFunction('dump', 'twig_var_dump', array('is_safe' => $isDumpOutputHtmlSafe ? array('html') : array(), 'needs_context' => true, 'needs_environment' => true)), - ); + return [ + new TwigFunction('dump', 'twig_var_dump', ['is_safe' => $isDumpOutputHtmlSafe ? ['html'] : [], 'needs_context' => true, 'needs_environment' => true, 'is_variadic' => true]), + ]; } public function getName() @@ -37,7 +40,15 @@ class Twig_Extension_Debug extends Twig_Extension } } -function twig_var_dump(Twig_Environment $env, $context) +class_alias('Twig\Extension\DebugExtension', 'Twig_Extension_Debug'); +} + +namespace { +use Twig\Environment; +use Twig\Template; +use Twig\TemplateWrapper; + +function twig_var_dump(Environment $env, $context, array $vars = []) { if (!$env->isDebug()) { return; @@ -45,23 +56,21 @@ function twig_var_dump(Twig_Environment $env, $context) ob_start(); - $count = func_num_args(); - if (2 === $count) { - $vars = array(); + if (!$vars) { + $vars = []; foreach ($context as $key => $value) { - if (!$value instanceof Twig_Template) { + if (!$value instanceof Template && !$value instanceof TemplateWrapper) { $vars[$key] = $value; } } var_dump($vars); } else { - for ($i = 2; $i < $count; ++$i) { - var_dump(func_get_arg($i)); + foreach ($vars as $var) { + var_dump($var); } } return ob_get_clean(); } - -class_alias('Twig_Extension_Debug', 'Twig\Extension\DebugExtension', false); +} diff --git a/system/libs/Twig/Extension/Escaper.php b/system/libs/Twig/Extension/EscaperExtension.php old mode 100755 new mode 100644 similarity index 76% rename from system/libs/Twig/Extension/Escaper.php rename to system/libs/Twig/Extension/EscaperExtension.php index 46c2d84b..fc7f6dfe --- a/system/libs/Twig/Extension/Escaper.php +++ b/system/libs/Twig/Extension/EscaperExtension.php @@ -9,10 +9,15 @@ * file that was distributed with this source code. */ +namespace Twig\Extension { +use Twig\NodeVisitor\EscaperNodeVisitor; +use Twig\TokenParser\AutoEscapeTokenParser; +use Twig\TwigFilter; + /** * @final */ -class Twig_Extension_Escaper extends Twig_Extension +class EscaperExtension extends AbstractExtension { protected $defaultStrategy; @@ -28,19 +33,19 @@ class Twig_Extension_Escaper extends Twig_Extension public function getTokenParsers() { - return array(new Twig_TokenParser_AutoEscape()); + return [new AutoEscapeTokenParser()]; } public function getNodeVisitors() { - return array(new Twig_NodeVisitor_Escaper()); + return [new EscaperNodeVisitor()]; } public function getFilters() { - return array( - new Twig_SimpleFilter('raw', 'twig_raw_filter', array('is_safe' => array('all'))), - ); + return [ + new TwigFilter('raw', 'twig_raw_filter', ['is_safe' => ['all']]), + ]; } /** @@ -67,7 +72,7 @@ class Twig_Extension_Escaper extends Twig_Extension } if ('name' === $defaultStrategy) { - $defaultStrategy = array('Twig_FileExtensionEscapingStrategy', 'guess'); + $defaultStrategy = ['\Twig\FileExtensionEscapingStrategy', 'guess']; } $this->defaultStrategy = $defaultStrategy; @@ -84,8 +89,8 @@ class Twig_Extension_Escaper extends Twig_Extension { // disable string callables to avoid calling a function named html or js, // or any other upcoming escaping strategy - if (!is_string($this->defaultStrategy) && false !== $this->defaultStrategy) { - return call_user_func($this->defaultStrategy, $name); + if (!\is_string($this->defaultStrategy) && false !== $this->defaultStrategy) { + return \call_user_func($this->defaultStrategy, $name); } return $this->defaultStrategy; @@ -97,6 +102,10 @@ class Twig_Extension_Escaper extends Twig_Extension } } +class_alias('Twig\Extension\EscaperExtension', 'Twig_Extension_Escaper'); +} + +namespace { /** * Marks a variable as being safe. * @@ -108,5 +117,4 @@ function twig_raw_filter($string) { return $string; } - -class_alias('Twig_Extension_Escaper', 'Twig\Extension\EscaperExtension', false); +} diff --git a/system/libs/Twig/ExtensionInterface.php b/system/libs/Twig/Extension/ExtensionInterface.php old mode 100755 new mode 100644 similarity index 70% rename from system/libs/Twig/ExtensionInterface.php rename to system/libs/Twig/Extension/ExtensionInterface.php index 946df500..72b31e9d --- a/system/libs/Twig/ExtensionInterface.php +++ b/system/libs/Twig/Extension/ExtensionInterface.php @@ -9,54 +9,63 @@ * file that was distributed with this source code. */ +namespace Twig\Extension; + +use Twig\Environment; +use Twig\NodeVisitor\NodeVisitorInterface; +use Twig\TokenParser\TokenParserInterface; +use Twig\TwigFilter; +use Twig\TwigFunction; +use Twig\TwigTest; + /** * Interface implemented by extension classes. * * @author Fabien Potencier */ -interface Twig_ExtensionInterface +interface ExtensionInterface { /** * Initializes the runtime environment. * * This is where you can load some file that contains filter functions for instance. * - * @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead + * @deprecated since 1.23 (to be removed in 2.0), implement \Twig_Extension_InitRuntimeInterface instead */ - public function initRuntime(Twig_Environment $environment); + public function initRuntime(Environment $environment); /** * Returns the token parser instances to add to the existing list. * - * @return Twig_TokenParserInterface[] + * @return TokenParserInterface[] */ public function getTokenParsers(); /** * Returns the node visitor instances to add to the existing list. * - * @return Twig_NodeVisitorInterface[] + * @return NodeVisitorInterface[] */ public function getNodeVisitors(); /** * Returns a list of filters to add to the existing list. * - * @return Twig_SimpleFilter[] + * @return TwigFilter[] */ public function getFilters(); /** * Returns a list of tests to add to the existing list. * - * @return Twig_SimpleTest[] + * @return TwigTest[] */ public function getTests(); /** * Returns a list of functions to add to the existing list. * - * @return Twig_SimpleFunction[] + * @return TwigFunction[] */ public function getFunctions(); @@ -72,7 +81,7 @@ interface Twig_ExtensionInterface * * @return array An array of global variables * - * @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_GlobalsInterface instead + * @deprecated since 1.23 (to be removed in 2.0), implement \Twig_Extension_GlobalsInterface instead */ public function getGlobals(); @@ -86,5 +95,7 @@ interface Twig_ExtensionInterface public function getName(); } -class_alias('Twig_ExtensionInterface', 'Twig\Extension\ExtensionInterface', false); -class_exists('Twig_Environment'); +class_alias('Twig\Extension\ExtensionInterface', 'Twig_ExtensionInterface'); + +// Ensure that the aliased name is loaded to keep BC for classes implementing the typehint with the old aliased name. +class_exists('Twig\Environment'); diff --git a/system/libs/Twig/Extension/GlobalsInterface.php b/system/libs/Twig/Extension/GlobalsInterface.php index 922cd2c9..1f54e257 100644 --- a/system/libs/Twig/Extension/GlobalsInterface.php +++ b/system/libs/Twig/Extension/GlobalsInterface.php @@ -9,16 +9,18 @@ * file that was distributed with this source code. */ +namespace Twig\Extension; + /** - * Enables usage of the deprecated Twig_Extension::getGlobals() method. + * Enables usage of the deprecated Twig\Extension\AbstractExtension::getGlobals() method. * * Explicitly implement this interface if you really need to implement the * deprecated getGlobals() method in your extensions. * * @author Fabien Potencier */ -interface Twig_Extension_GlobalsInterface +interface GlobalsInterface { } -class_alias('Twig_Extension_GlobalsInterface', 'Twig\Extension\GlobalsInterface', false); +class_alias('Twig\Extension\GlobalsInterface', 'Twig_Extension_GlobalsInterface'); diff --git a/system/libs/Twig/Extension/InitRuntimeInterface.php b/system/libs/Twig/Extension/InitRuntimeInterface.php index 1549862f..f71d9cb5 100644 --- a/system/libs/Twig/Extension/InitRuntimeInterface.php +++ b/system/libs/Twig/Extension/InitRuntimeInterface.php @@ -9,16 +9,18 @@ * file that was distributed with this source code. */ +namespace Twig\Extension; + /** - * Enables usage of the deprecated Twig_Extension::initRuntime() method. + * Enables usage of the deprecated Twig\Extension\AbstractExtension::initRuntime() method. * * Explicitly implement this interface if you really need to implement the * deprecated initRuntime() method in your extensions. * * @author Fabien Potencier */ -interface Twig_Extension_InitRuntimeInterface +interface InitRuntimeInterface { } -class_alias('Twig_Extension_InitRuntimeInterface', 'Twig\Extension\InitRuntimeInterface', false); +class_alias('Twig\Extension\InitRuntimeInterface', 'Twig_Extension_InitRuntimeInterface'); diff --git a/system/libs/Twig/Extension/Optimizer.php b/system/libs/Twig/Extension/OptimizerExtension.php old mode 100755 new mode 100644 similarity index 64% rename from system/libs/Twig/Extension/Optimizer.php rename to system/libs/Twig/Extension/OptimizerExtension.php index 6c62e3ef..3e137409 --- a/system/libs/Twig/Extension/Optimizer.php +++ b/system/libs/Twig/Extension/OptimizerExtension.php @@ -9,10 +9,14 @@ * file that was distributed with this source code. */ +namespace Twig\Extension; + +use Twig\NodeVisitor\OptimizerNodeVisitor; + /** * @final */ -class Twig_Extension_Optimizer extends Twig_Extension +class OptimizerExtension extends AbstractExtension { protected $optimizers; @@ -23,7 +27,7 @@ class Twig_Extension_Optimizer extends Twig_Extension public function getNodeVisitors() { - return array(new Twig_NodeVisitor_Optimizer($this->optimizers)); + return [new OptimizerNodeVisitor($this->optimizers)]; } public function getName() @@ -32,4 +36,4 @@ class Twig_Extension_Optimizer extends Twig_Extension } } -class_alias('Twig_Extension_Optimizer', 'Twig\Extension\OptimizerExtension', false); +class_alias('Twig\Extension\OptimizerExtension', 'Twig_Extension_Optimizer'); diff --git a/system/libs/Twig/Extension/Profiler.php b/system/libs/Twig/Extension/ProfilerExtension.php old mode 100755 new mode 100644 similarity index 54% rename from system/libs/Twig/Extension/Profiler.php rename to system/libs/Twig/Extension/ProfilerExtension.php index fcfc002b..7b21b9fa --- a/system/libs/Twig/Extension/Profiler.php +++ b/system/libs/Twig/Extension/ProfilerExtension.php @@ -9,34 +9,39 @@ * file that was distributed with this source code. */ -class Twig_Extension_Profiler extends Twig_Extension -{ - private $actives = array(); +namespace Twig\Extension; - public function __construct(Twig_Profiler_Profile $profile) +use Twig\Profiler\NodeVisitor\ProfilerNodeVisitor; +use Twig\Profiler\Profile; + +class ProfilerExtension extends AbstractExtension +{ + private $actives = []; + + public function __construct(Profile $profile) { $this->actives[] = $profile; } - public function enter(Twig_Profiler_Profile $profile) + public function enter(Profile $profile) { $this->actives[0]->addProfile($profile); array_unshift($this->actives, $profile); } - public function leave(Twig_Profiler_Profile $profile) + public function leave(Profile $profile) { $profile->leave(); array_shift($this->actives); - if (1 === count($this->actives)) { + if (1 === \count($this->actives)) { $this->actives[0]->leave(); } } public function getNodeVisitors() { - return array(new Twig_Profiler_NodeVisitor_Profiler(get_class($this))); + return [new ProfilerNodeVisitor(\get_class($this))]; } public function getName() @@ -45,5 +50,4 @@ class Twig_Extension_Profiler extends Twig_Extension } } -class_alias('Twig_Extension_Profiler', 'Twig\Extension\ProfilerExtension', false); -class_exists('Twig_Profiler_Profile'); +class_alias('Twig\Extension\ProfilerExtension', 'Twig_Extension_Profiler'); diff --git a/system/libs/Twig/Extension/RuntimeExtensionInterface.php b/system/libs/Twig/Extension/RuntimeExtensionInterface.php new file mode 100644 index 00000000..63bc3b1a --- /dev/null +++ b/system/libs/Twig/Extension/RuntimeExtensionInterface.php @@ -0,0 +1,19 @@ + + */ +interface RuntimeExtensionInterface +{ +} diff --git a/system/libs/Twig/Extension/Sandbox.php b/system/libs/Twig/Extension/SandboxExtension.php old mode 100755 new mode 100644 similarity index 74% rename from system/libs/Twig/Extension/Sandbox.php rename to system/libs/Twig/Extension/SandboxExtension.php index 5cb80a71..818c8c94 --- a/system/libs/Twig/Extension/Sandbox.php +++ b/system/libs/Twig/Extension/SandboxExtension.php @@ -9,16 +9,22 @@ * file that was distributed with this source code. */ +namespace Twig\Extension; + +use Twig\NodeVisitor\SandboxNodeVisitor; +use Twig\Sandbox\SecurityPolicyInterface; +use Twig\TokenParser\SandboxTokenParser; + /** * @final */ -class Twig_Extension_Sandbox extends Twig_Extension +class SandboxExtension extends AbstractExtension { protected $sandboxedGlobally; protected $sandboxed; protected $policy; - public function __construct(Twig_Sandbox_SecurityPolicyInterface $policy, $sandboxed = false) + public function __construct(SecurityPolicyInterface $policy, $sandboxed = false) { $this->policy = $policy; $this->sandboxedGlobally = $sandboxed; @@ -26,12 +32,12 @@ class Twig_Extension_Sandbox extends Twig_Extension public function getTokenParsers() { - return array(new Twig_TokenParser_Sandbox()); + return [new SandboxTokenParser()]; } public function getNodeVisitors() { - return array(new Twig_NodeVisitor_Sandbox()); + return [new SandboxNodeVisitor()]; } public function enableSandbox() @@ -54,7 +60,7 @@ class Twig_Extension_Sandbox extends Twig_Extension return $this->sandboxedGlobally; } - public function setSecurityPolicy(Twig_Sandbox_SecurityPolicyInterface $policy) + public function setSecurityPolicy(SecurityPolicyInterface $policy) { $this->policy = $policy; } @@ -87,7 +93,7 @@ class Twig_Extension_Sandbox extends Twig_Extension public function ensureToStringAllowed($obj) { - if ($this->isSandboxed() && is_object($obj)) { + if ($this->isSandboxed() && \is_object($obj) && method_exists($obj, '__toString')) { $this->policy->checkMethodAllowed($obj, '__toString'); } @@ -100,4 +106,4 @@ class Twig_Extension_Sandbox extends Twig_Extension } } -class_alias('Twig_Extension_Sandbox', 'Twig\Extension\SandboxExtension', false); +class_alias('Twig\Extension\SandboxExtension', 'Twig_Extension_Sandbox'); diff --git a/system/libs/Twig/Extension/Staging.php b/system/libs/Twig/Extension/StagingExtension.php old mode 100755 new mode 100644 similarity index 78% rename from system/libs/Twig/Extension/Staging.php rename to system/libs/Twig/Extension/StagingExtension.php index d3a0f9c9..049c5c79 --- a/system/libs/Twig/Extension/Staging.php +++ b/system/libs/Twig/Extension/StagingExtension.php @@ -9,23 +9,28 @@ * file that was distributed with this source code. */ +namespace Twig\Extension; + +use Twig\NodeVisitor\NodeVisitorInterface; +use Twig\TokenParser\TokenParserInterface; + /** * Internal class. * - * This class is used by Twig_Environment as a staging area and must not be used directly. + * This class is used by \Twig\Environment as a staging area and must not be used directly. * * @author Fabien Potencier * * @internal */ -class Twig_Extension_Staging extends Twig_Extension +class StagingExtension extends AbstractExtension { - protected $functions = array(); - protected $filters = array(); - protected $visitors = array(); - protected $tokenParsers = array(); - protected $globals = array(); - protected $tests = array(); + protected $functions = []; + protected $filters = []; + protected $visitors = []; + protected $tokenParsers = []; + protected $globals = []; + protected $tests = []; public function addFunction($name, $function) { @@ -55,7 +60,7 @@ class Twig_Extension_Staging extends Twig_Extension return $this->filters; } - public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) + public function addNodeVisitor(NodeVisitorInterface $visitor) { $this->visitors[] = $visitor; } @@ -65,7 +70,7 @@ class Twig_Extension_Staging extends Twig_Extension return $this->visitors; } - public function addTokenParser(Twig_TokenParserInterface $parser) + public function addTokenParser(TokenParserInterface $parser) { if (isset($this->tokenParsers[$parser->getTag()])) { @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); @@ -109,4 +114,4 @@ class Twig_Extension_Staging extends Twig_Extension } } -class_alias('Twig_Extension_Staging', 'Twig\Extension\StagingExtension', false); +class_alias('Twig\Extension\StagingExtension', 'Twig_Extension_Staging'); diff --git a/system/libs/Twig/Extension/StringLoader.php b/system/libs/Twig/Extension/StringLoader.php deleted file mode 100755 index 2ce3c992..00000000 --- a/system/libs/Twig/Extension/StringLoader.php +++ /dev/null @@ -1,47 +0,0 @@ - true)), - ); - } - - public function getName() - { - return 'string_loader'; - } -} - -/** - * Loads a template from a string. - * - *
- * {{ include(template_from_string("Hello {{ name }}")) }}
- * 
- * - * @param Twig_Environment $env A Twig_Environment instance - * @param string $template A template as a string or object implementing __toString() - * - * @return Twig_Template - */ -function twig_template_from_string(Twig_Environment $env, $template) -{ - return $env->createTemplate((string) $template); -} - -class_alias('Twig_Extension_StringLoader', 'Twig\Extension\StringLoaderExtension', false); diff --git a/system/libs/Twig/Extension/StringLoaderExtension.php b/system/libs/Twig/Extension/StringLoaderExtension.php new file mode 100644 index 00000000..93ac834a --- /dev/null +++ b/system/libs/Twig/Extension/StringLoaderExtension.php @@ -0,0 +1,54 @@ + true]), + ]; + } + + public function getName() + { + return 'string_loader'; + } +} + +class_alias('Twig\Extension\StringLoaderExtension', 'Twig_Extension_StringLoader'); +} + +namespace { +use Twig\Environment; +use Twig\TemplateWrapper; + +/** + * Loads a template from a string. + * + * {{ include(template_from_string("Hello {{ name }}")) }} + * + * @param string $template A template as a string or object implementing __toString() + * @param string $name An optional name of the template to be used in error messages + * + * @return TemplateWrapper + */ +function twig_template_from_string(Environment $env, $template, $name = null) +{ + return $env->createTemplate((string) $template, $name); +} +} diff --git a/system/libs/Twig/FileExtensionEscapingStrategy.php b/system/libs/Twig/FileExtensionEscapingStrategy.php index 8f8cd2ee..bc95f334 100755 --- a/system/libs/Twig/FileExtensionEscapingStrategy.php +++ b/system/libs/Twig/FileExtensionEscapingStrategy.php @@ -9,6 +9,8 @@ * file that was distributed with this source code. */ +namespace Twig; + /** * Default autoescaping strategy based on file names. * @@ -20,7 +22,7 @@ * * @author Fabien Potencier */ -class Twig_FileExtensionEscapingStrategy +class FileExtensionEscapingStrategy { /** * Guesses the best autoescaping strategy based on the file name. @@ -31,7 +33,7 @@ class Twig_FileExtensionEscapingStrategy */ public static function guess($name) { - if (in_array(substr($name, -1), array('/', '\\'))) { + if (\in_array(substr($name, -1), ['/', '\\'])) { return 'html'; // return html for directories } @@ -57,4 +59,4 @@ class Twig_FileExtensionEscapingStrategy } } -class_alias('Twig_FileExtensionEscapingStrategy', 'Twig\FileExtensionEscapingStrategy', false); +class_alias('Twig\FileExtensionEscapingStrategy', 'Twig_FileExtensionEscapingStrategy'); diff --git a/system/libs/Twig/Lexer.php b/system/libs/Twig/Lexer.php index 85390b28..697a6cfa 100755 --- a/system/libs/Twig/Lexer.php +++ b/system/libs/Twig/Lexer.php @@ -10,12 +10,16 @@ * file that was distributed with this source code. */ +namespace Twig; + +use Twig\Error\SyntaxError; + /** * Lexes a template string. * * @author Fabien Potencier */ -class Twig_Lexer implements Twig_LexerInterface +class Lexer implements \Twig_LexerInterface { protected $tokens; protected $code; @@ -43,43 +47,124 @@ class Twig_Lexer implements Twig_LexerInterface const STATE_INTERPOLATION = 4; const REGEX_NAME = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A'; - const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A'; + const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?([Ee][\+\-][0-9]+)?/A'; const REGEX_STRING = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As'; const REGEX_DQ_STRING_DELIM = '/"/A'; const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As'; const PUNCTUATION = '()[]{}?:.,|'; - public function __construct(Twig_Environment $env, array $options = array()) + public function __construct(Environment $env, array $options = []) { $this->env = $env; - $this->options = array_merge(array( - 'tag_comment' => array('{#', '#}'), - 'tag_block' => array('{%', '%}'), - 'tag_variable' => array('{{', '}}'), + $this->options = array_merge([ + 'tag_comment' => ['{#', '#}'], + 'tag_block' => ['{%', '%}'], + 'tag_variable' => ['{{', '}}'], 'whitespace_trim' => '-', - 'interpolation' => array('#{', '}'), - ), $options); + 'whitespace_line_trim' => '~', + 'whitespace_line_chars' => ' \t\0\x0B', + 'interpolation' => ['#{', '}'], + ], $options); + + // when PHP 7.3 is the min version, we will be able to remove the '#' part in preg_quote as it's part of the default + $this->regexes = [ + // }} + 'lex_var' => '{ + \s* + (?:'. + preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '#').'\s*'. // -}}\s* + '|'. + preg_quote($this->options['whitespace_line_trim'].$this->options['tag_variable'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~}}[ \t\0\x0B]* + '|'. + preg_quote($this->options['tag_variable'][1], '#'). // }} + ') + }Ax', + + // %} + 'lex_block' => '{ + \s* + (?:'. + preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '#').'\s*\n?'. // -%}\s*\n? + '|'. + preg_quote($this->options['whitespace_line_trim'].$this->options['tag_block'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~%}[ \t\0\x0B]* + '|'. + preg_quote($this->options['tag_block'][1], '#').'\n?'. // %}\n? + ') + }Ax', + + // {% endverbatim %} + 'lex_raw_data' => '{'. + preg_quote($this->options['tag_block'][0], '#'). // {% + '('. + $this->options['whitespace_trim']. // - + '|'. + $this->options['whitespace_line_trim']. // ~ + ')?\s*'. + '(?:end%s)'. // endraw or endverbatim + '\s*'. + '(?:'. + preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '#').'\s*'. // -%} + '|'. + preg_quote($this->options['whitespace_line_trim'].$this->options['tag_block'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~%}[ \t\0\x0B]* + '|'. + preg_quote($this->options['tag_block'][1], '#'). // %} + ') + }sx', - $this->regexes = array( - 'lex_var' => '/\s*'.preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_variable'][1], '/').'/A', - 'lex_block' => '/\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')\n?/A', - 'lex_raw_data' => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*(?:end%s)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s', 'operator' => $this->getOperatorRegex(), - 'lex_comment' => '/(?:'.preg_quote($this->options['whitespace_trim'], '/').preg_quote($this->options['tag_comment'][1], '/').'\s*|'.preg_quote($this->options['tag_comment'][1], '/').')\n?/s', - 'lex_block_raw' => '/\s*(raw|verbatim)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As', - 'lex_block_line' => '/\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '/').'/As', - 'lex_tokens_start' => '/('.preg_quote($this->options['tag_variable'][0], '/').'|'.preg_quote($this->options['tag_block'][0], '/').'|'.preg_quote($this->options['tag_comment'][0], '/').')('.preg_quote($this->options['whitespace_trim'], '/').')?/s', - 'interpolation_start' => '/'.preg_quote($this->options['interpolation'][0], '/').'\s*/A', - 'interpolation_end' => '/\s*'.preg_quote($this->options['interpolation'][1], '/').'/A', - ); + + // #} + 'lex_comment' => '{ + (?:'. + preg_quote($this->options['whitespace_trim']).preg_quote($this->options['tag_comment'][1], '#').'\s*\n?'. // -#}\s*\n? + '|'. + preg_quote($this->options['whitespace_line_trim'].$this->options['tag_comment'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~#}[ \t\0\x0B]* + '|'. + preg_quote($this->options['tag_comment'][1], '#').'\n?'. // #}\n? + ') + }sx', + + // verbatim %} + 'lex_block_raw' => '{ + \s* + (raw|verbatim) + \s* + (?:'. + preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '#').'\s*'. // -%}\s* + '|'. + preg_quote($this->options['whitespace_line_trim'].$this->options['tag_block'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~%}[ \t\0\x0B]* + '|'. + preg_quote($this->options['tag_block'][1], '#'). // %} + ') + }Asx', + + 'lex_block_line' => '{\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '#').'}As', + + // {{ or {% or {# + 'lex_tokens_start' => '{ + ('. + preg_quote($this->options['tag_variable'][0], '#'). // {{ + '|'. + preg_quote($this->options['tag_block'][0], '#'). // {% + '|'. + preg_quote($this->options['tag_comment'][0], '#'). // {# + ')('. + preg_quote($this->options['whitespace_trim'], '#'). // - + '|'. + preg_quote($this->options['whitespace_line_trim'], '#'). // ~ + ')? + }sx', + 'interpolation_start' => '{'.preg_quote($this->options['interpolation'][0], '#').'\s*}A', + 'interpolation_end' => '{\s*'.preg_quote($this->options['interpolation'][1], '#').'}A', + ]; } public function tokenize($code, $name = null) { - if (!$code instanceof Twig_Source) { - @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); - $this->source = new Twig_Source($code, $name); + if (!$code instanceof Source) { + @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); + $this->source = new Source($code, $name); } else { $this->source = $code; } @@ -88,22 +173,22 @@ class Twig_Lexer implements Twig_LexerInterface @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); } - if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { + if (\function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { $mbEncoding = mb_internal_encoding(); mb_internal_encoding('ASCII'); } else { $mbEncoding = null; } - $this->code = str_replace(array("\r\n", "\r"), "\n", $this->source->getCode()); + $this->code = str_replace(["\r\n", "\r"], "\n", $this->source->getCode()); $this->filename = $this->source->getName(); $this->cursor = 0; $this->lineno = 1; - $this->end = strlen($this->code); - $this->tokens = array(); + $this->end = \strlen($this->code); + $this->tokens = []; $this->state = self::STATE_DATA; - $this->states = array(); - $this->brackets = array(); + $this->states = []; + $this->brackets = []; $this->position = -1; // find all token starts in one go @@ -136,25 +221,25 @@ class Twig_Lexer implements Twig_LexerInterface } } - $this->pushToken(Twig_Token::EOF_TYPE); + $this->pushToken(Token::EOF_TYPE); if (!empty($this->brackets)) { list($expect, $lineno) = array_pop($this->brackets); - throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); + throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); } if ($mbEncoding) { mb_internal_encoding($mbEncoding); } - return new Twig_TokenStream($this->tokens, $this->source); + return new TokenStream($this->tokens, $this->source); } protected function lexData() { // if no matches are left we return the rest of the template as simple text token - if ($this->position == count($this->positions[0]) - 1) { - $this->pushToken(Twig_Token::TEXT_TYPE, substr($this->code, $this->cursor)); + if ($this->position == \count($this->positions[0]) - 1) { + $this->pushToken(Token::TEXT_TYPE, substr($this->code, $this->cursor)); $this->cursor = $this->end; return; @@ -163,7 +248,7 @@ class Twig_Lexer implements Twig_LexerInterface // Find the first token after the current cursor $position = $this->positions[0][++$this->position]; while ($position[1] < $this->cursor) { - if ($this->position == count($this->positions[0]) - 1) { + if ($this->position == \count($this->positions[0]) - 1) { return; } $position = $this->positions[0][++$this->position]; @@ -171,10 +256,19 @@ class Twig_Lexer implements Twig_LexerInterface // push the template text first $text = $textContent = substr($this->code, $this->cursor, $position[1] - $this->cursor); + + // trim? if (isset($this->positions[2][$this->position][0])) { - $text = rtrim($text); + if ($this->options['whitespace_trim'] === $this->positions[2][$this->position][0]) { + // whitespace_trim detected ({%-, {{- or {#-) + $text = rtrim($text); + } elseif ($this->options['whitespace_line_trim'] === $this->positions[2][$this->position][0]) { + // whitespace_line_trim detected ({%~, {{~ or {#~) + // don't trim \r and \n + $text = rtrim($text, " \t\0\x0B"); + } } - $this->pushToken(Twig_Token::TEXT_TYPE, $text); + $this->pushToken(Token::TEXT_TYPE, $text); $this->moveCursor($textContent.$position[0]); switch ($this->positions[1][$this->position][0]) { @@ -184,22 +278,22 @@ class Twig_Lexer implements Twig_LexerInterface case $this->options['tag_block'][0]: // raw data? - if (preg_match($this->regexes['lex_block_raw'], $this->code, $match, null, $this->cursor)) { + if (preg_match($this->regexes['lex_block_raw'], $this->code, $match, 0, $this->cursor)) { $this->moveCursor($match[0]); $this->lexRawData($match[1]); // {% line \d+ %} - } elseif (preg_match($this->regexes['lex_block_line'], $this->code, $match, null, $this->cursor)) { + } elseif (preg_match($this->regexes['lex_block_line'], $this->code, $match, 0, $this->cursor)) { $this->moveCursor($match[0]); $this->lineno = (int) $match[1]; } else { - $this->pushToken(Twig_Token::BLOCK_START_TYPE); + $this->pushToken(Token::BLOCK_START_TYPE); $this->pushState(self::STATE_BLOCK); $this->currentVarBlockLine = $this->lineno; } break; case $this->options['tag_variable'][0]: - $this->pushToken(Twig_Token::VAR_START_TYPE); + $this->pushToken(Token::VAR_START_TYPE); $this->pushState(self::STATE_VAR); $this->currentVarBlockLine = $this->lineno; break; @@ -208,8 +302,8 @@ class Twig_Lexer implements Twig_LexerInterface protected function lexBlock() { - if (empty($this->brackets) && preg_match($this->regexes['lex_block'], $this->code, $match, null, $this->cursor)) { - $this->pushToken(Twig_Token::BLOCK_END_TYPE); + if (empty($this->brackets) && preg_match($this->regexes['lex_block'], $this->code, $match, 0, $this->cursor)) { + $this->pushToken(Token::BLOCK_END_TYPE); $this->moveCursor($match[0]); $this->popState(); } else { @@ -219,8 +313,8 @@ class Twig_Lexer implements Twig_LexerInterface protected function lexVar() { - if (empty($this->brackets) && preg_match($this->regexes['lex_var'], $this->code, $match, null, $this->cursor)) { - $this->pushToken(Twig_Token::VAR_END_TYPE); + if (empty($this->brackets) && preg_match($this->regexes['lex_var'], $this->code, $match, 0, $this->cursor)) { + $this->pushToken(Token::VAR_END_TYPE); $this->moveCursor($match[0]); $this->popState(); } else { @@ -231,68 +325,73 @@ class Twig_Lexer implements Twig_LexerInterface protected function lexExpression() { // whitespace - if (preg_match('/\s+/A', $this->code, $match, null, $this->cursor)) { + if (preg_match('/\s+/A', $this->code, $match, 0, $this->cursor)) { $this->moveCursor($match[0]); if ($this->cursor >= $this->end) { - throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $this->state === self::STATE_BLOCK ? 'block' : 'variable'), $this->currentVarBlockLine, $this->source); + throw new SyntaxError(sprintf('Unclosed "%s".', self::STATE_BLOCK === $this->state ? 'block' : 'variable'), $this->currentVarBlockLine, $this->source); } } + // arrow function + if ('=' === $this->code[$this->cursor] && '>' === $this->code[$this->cursor + 1]) { + $this->pushToken(Token::ARROW_TYPE, '=>'); + $this->moveCursor('=>'); + } // operators - if (preg_match($this->regexes['operator'], $this->code, $match, null, $this->cursor)) { - $this->pushToken(Twig_Token::OPERATOR_TYPE, preg_replace('/\s+/', ' ', $match[0])); + elseif (preg_match($this->regexes['operator'], $this->code, $match, 0, $this->cursor)) { + $this->pushToken(Token::OPERATOR_TYPE, preg_replace('/\s+/', ' ', $match[0])); $this->moveCursor($match[0]); } // names - elseif (preg_match(self::REGEX_NAME, $this->code, $match, null, $this->cursor)) { - $this->pushToken(Twig_Token::NAME_TYPE, $match[0]); + elseif (preg_match(self::REGEX_NAME, $this->code, $match, 0, $this->cursor)) { + $this->pushToken(Token::NAME_TYPE, $match[0]); $this->moveCursor($match[0]); } // numbers - elseif (preg_match(self::REGEX_NUMBER, $this->code, $match, null, $this->cursor)) { + elseif (preg_match(self::REGEX_NUMBER, $this->code, $match, 0, $this->cursor)) { $number = (float) $match[0]; // floats if (ctype_digit($match[0]) && $number <= PHP_INT_MAX) { $number = (int) $match[0]; // integers lower than the maximum } - $this->pushToken(Twig_Token::NUMBER_TYPE, $number); + $this->pushToken(Token::NUMBER_TYPE, $number); $this->moveCursor($match[0]); } // punctuation elseif (false !== strpos(self::PUNCTUATION, $this->code[$this->cursor])) { // opening bracket if (false !== strpos('([{', $this->code[$this->cursor])) { - $this->brackets[] = array($this->code[$this->cursor], $this->lineno); + $this->brackets[] = [$this->code[$this->cursor], $this->lineno]; } // closing bracket elseif (false !== strpos(')]}', $this->code[$this->cursor])) { if (empty($this->brackets)) { - throw new Twig_Error_Syntax(sprintf('Unexpected "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); + throw new SyntaxError(sprintf('Unexpected "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); } list($expect, $lineno) = array_pop($this->brackets); if ($this->code[$this->cursor] != strtr($expect, '([{', ')]}')) { - throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); + throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); } } - $this->pushToken(Twig_Token::PUNCTUATION_TYPE, $this->code[$this->cursor]); + $this->pushToken(Token::PUNCTUATION_TYPE, $this->code[$this->cursor]); ++$this->cursor; } // strings - elseif (preg_match(self::REGEX_STRING, $this->code, $match, null, $this->cursor)) { - $this->pushToken(Twig_Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1))); + elseif (preg_match(self::REGEX_STRING, $this->code, $match, 0, $this->cursor)) { + $this->pushToken(Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1))); $this->moveCursor($match[0]); } // opening double quoted string - elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) { - $this->brackets[] = array('"', $this->lineno); + elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, 0, $this->cursor)) { + $this->brackets[] = ['"', $this->lineno]; $this->pushState(self::STATE_STRING); $this->moveCursor($match[0]); } // unlexable else { - throw new Twig_Error_Syntax(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); + throw new SyntaxError(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); } } @@ -303,23 +402,31 @@ class Twig_Lexer implements Twig_LexerInterface } if (!preg_match(str_replace('%s', $tag, $this->regexes['lex_raw_data']), $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) { - throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "%s" block.', $tag), $this->lineno, $this->source); + throw new SyntaxError(sprintf('Unexpected end of file: Unclosed "%s" block.', $tag), $this->lineno, $this->source); } $text = substr($this->code, $this->cursor, $match[0][1] - $this->cursor); $this->moveCursor($text.$match[0][0]); - if (false !== strpos($match[1][0], $this->options['whitespace_trim'])) { - $text = rtrim($text); + // trim? + if (isset($match[1][0])) { + if ($this->options['whitespace_trim'] === $match[1][0]) { + // whitespace_trim detected ({%-, {{- or {#-) + $text = rtrim($text); + } else { + // whitespace_line_trim detected ({%~, {{~ or {#~) + // don't trim \r and \n + $text = rtrim($text, " \t\0\x0B"); + } } - $this->pushToken(Twig_Token::TEXT_TYPE, $text); + $this->pushToken(Token::TEXT_TYPE, $text); } protected function lexComment() { if (!preg_match($this->regexes['lex_comment'], $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) { - throw new Twig_Error_Syntax('Unclosed comment.', $this->lineno, $this->source); + throw new SyntaxError('Unclosed comment.', $this->lineno, $this->source); } $this->moveCursor(substr($this->code, $this->cursor, $match[0][1] - $this->cursor).$match[0][0]); @@ -327,31 +434,34 @@ class Twig_Lexer implements Twig_LexerInterface protected function lexString() { - if (preg_match($this->regexes['interpolation_start'], $this->code, $match, null, $this->cursor)) { - $this->brackets[] = array($this->options['interpolation'][0], $this->lineno); - $this->pushToken(Twig_Token::INTERPOLATION_START_TYPE); + if (preg_match($this->regexes['interpolation_start'], $this->code, $match, 0, $this->cursor)) { + $this->brackets[] = [$this->options['interpolation'][0], $this->lineno]; + $this->pushToken(Token::INTERPOLATION_START_TYPE); $this->moveCursor($match[0]); $this->pushState(self::STATE_INTERPOLATION); - } elseif (preg_match(self::REGEX_DQ_STRING_PART, $this->code, $match, null, $this->cursor) && strlen($match[0]) > 0) { - $this->pushToken(Twig_Token::STRING_TYPE, stripcslashes($match[0])); + } elseif (preg_match(self::REGEX_DQ_STRING_PART, $this->code, $match, 0, $this->cursor) && \strlen($match[0]) > 0) { + $this->pushToken(Token::STRING_TYPE, stripcslashes($match[0])); $this->moveCursor($match[0]); - } elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) { + } elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, 0, $this->cursor)) { list($expect, $lineno) = array_pop($this->brackets); - if ($this->code[$this->cursor] != '"') { - throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); + if ('"' != $this->code[$this->cursor]) { + throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); } $this->popState(); ++$this->cursor; + } else { + // unlexable + throw new SyntaxError(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); } } protected function lexInterpolation() { $bracket = end($this->brackets); - if ($this->options['interpolation'][0] === $bracket[0] && preg_match($this->regexes['interpolation_end'], $this->code, $match, null, $this->cursor)) { + if ($this->options['interpolation'][0] === $bracket[0] && preg_match($this->regexes['interpolation_end'], $this->code, $match, 0, $this->cursor)) { array_pop($this->brackets); - $this->pushToken(Twig_Token::INTERPOLATION_END_TYPE); + $this->pushToken(Token::INTERPOLATION_END_TYPE); $this->moveCursor($match[0]); $this->popState(); } else { @@ -362,23 +472,23 @@ class Twig_Lexer implements Twig_LexerInterface protected function pushToken($type, $value = '') { // do not push empty text tokens - if (Twig_Token::TEXT_TYPE === $type && '' === $value) { + if (Token::TEXT_TYPE === $type && '' === $value) { return; } - $this->tokens[] = new Twig_Token($type, $value, $this->lineno); + $this->tokens[] = new Token($type, $value, $this->lineno); } protected function moveCursor($text) { - $this->cursor += strlen($text); + $this->cursor += \strlen($text); $this->lineno += substr_count($text, "\n"); } protected function getOperatorRegex() { $operators = array_merge( - array('='), + ['='], array_keys($this->env->getUnaryOperators()), array_keys($this->env->getBinaryOperators()) ); @@ -386,7 +496,7 @@ class Twig_Lexer implements Twig_LexerInterface $operators = array_combine($operators, array_map('strlen', $operators)); arsort($operators); - $regex = array(); + $regex = []; foreach ($operators as $operator => $length) { // an operator that ends with a character must be followed by // a whitespace or a parenthesis @@ -413,12 +523,12 @@ class Twig_Lexer implements Twig_LexerInterface protected function popState() { - if (0 === count($this->states)) { - throw new Exception('Cannot pop state without a previous state.'); + if (0 === \count($this->states)) { + throw new \LogicException('Cannot pop state without a previous state.'); } $this->state = array_pop($this->states); } } -class_alias('Twig_Lexer', 'Twig\Lexer', false); +class_alias('Twig\Lexer', 'Twig_Lexer'); diff --git a/system/libs/Twig/Loader/Array.php b/system/libs/Twig/Loader/ArrayLoader.php old mode 100755 new mode 100644 similarity index 71% rename from system/libs/Twig/Loader/Array.php rename to system/libs/Twig/Loader/ArrayLoader.php index 0aac7690..6bc430f5 --- a/system/libs/Twig/Loader/Array.php +++ b/system/libs/Twig/Loader/ArrayLoader.php @@ -9,6 +9,11 @@ * file that was distributed with this source code. */ +namespace Twig\Loader; + +use Twig\Error\LoaderError; +use Twig\Source; + /** * Loads a template from an array. * @@ -23,14 +28,14 @@ * * @author Fabien Potencier */ -class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface +class ArrayLoader implements LoaderInterface, ExistsLoaderInterface, SourceContextLoaderInterface { - protected $templates = array(); + protected $templates = []; /** * @param array $templates An array of templates (keys are the names, and values are the source code) */ - public function __construct(array $templates = array()) + public function __construct(array $templates = []) { $this->templates = $templates; } @@ -48,11 +53,11 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf public function getSource($name) { - @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED); + @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', \get_class($this)), E_USER_DEPRECATED); $name = (string) $name; if (!isset($this->templates[$name])) { - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); + throw new LoaderError(sprintf('Template "%s" is not defined.', $name)); } return $this->templates[$name]; @@ -62,10 +67,10 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf { $name = (string) $name; if (!isset($this->templates[$name])) { - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); + throw new LoaderError(sprintf('Template "%s" is not defined.', $name)); } - return new Twig_Source($this->templates[$name], $name); + return new Source($this->templates[$name], $name); } public function exists($name) @@ -77,7 +82,7 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf { $name = (string) $name; if (!isset($this->templates[$name])) { - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); + throw new LoaderError(sprintf('Template "%s" is not defined.', $name)); } return $name.':'.$this->templates[$name]; @@ -87,11 +92,11 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf { $name = (string) $name; if (!isset($this->templates[$name])) { - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); + throw new LoaderError(sprintf('Template "%s" is not defined.', $name)); } return true; } } -class_alias('Twig_Loader_Array', 'Twig\Loader\ArrayLoader', false); +class_alias('Twig\Loader\ArrayLoader', 'Twig_Loader_Array'); diff --git a/system/libs/Twig/Loader/Chain.php b/system/libs/Twig/Loader/ChainLoader.php old mode 100755 new mode 100644 similarity index 50% rename from system/libs/Twig/Loader/Chain.php rename to system/libs/Twig/Loader/ChainLoader.php index 59a33796..25ac55a3 --- a/system/libs/Twig/Loader/Chain.php +++ b/system/libs/Twig/Loader/ChainLoader.php @@ -9,6 +9,11 @@ * file that was distributed with this source code. */ +namespace Twig\Loader; + +use Twig\Error\LoaderError; +use Twig\Source; + /** * Loads templates from other loaders. * @@ -16,67 +21,75 @@ * * @author Fabien Potencier */ -class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface +class ChainLoader implements LoaderInterface, ExistsLoaderInterface, SourceContextLoaderInterface { - private $hasSourceCache = array(); - protected $loaders = array(); + private $hasSourceCache = []; + protected $loaders = []; /** - * @param Twig_LoaderInterface[] $loaders + * @param LoaderInterface[] $loaders */ - public function __construct(array $loaders = array()) + public function __construct(array $loaders = []) { foreach ($loaders as $loader) { $this->addLoader($loader); } } - public function addLoader(Twig_LoaderInterface $loader) + public function addLoader(LoaderInterface $loader) { $this->loaders[] = $loader; - $this->hasSourceCache = array(); + $this->hasSourceCache = []; + } + + /** + * @return LoaderInterface[] + */ + public function getLoaders() + { + return $this->loaders; } public function getSource($name) { - @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED); + @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', \get_class($this)), E_USER_DEPRECATED); - $exceptions = array(); + $exceptions = []; foreach ($this->loaders as $loader) { - if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { + if ($loader instanceof ExistsLoaderInterface && !$loader->exists($name)) { continue; } try { return $loader->getSource($name); - } catch (Twig_Error_Loader $e) { + } catch (LoaderError $e) { $exceptions[] = $e->getMessage(); } } - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); + throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); } public function getSourceContext($name) { - $exceptions = array(); + $exceptions = []; foreach ($this->loaders as $loader) { - if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { + if ($loader instanceof ExistsLoaderInterface && !$loader->exists($name)) { continue; } try { - if ($loader instanceof Twig_SourceContextLoaderInterface) { + if ($loader instanceof SourceContextLoaderInterface) { return $loader->getSourceContext($name); } - return new Twig_Source($loader->getSource($name), $name); - } catch (Twig_Error_Loader $e) { + return new Source($loader->getSource($name), $name); + } catch (LoaderError $e) { $exceptions[] = $e->getMessage(); } } - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); + throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); } public function exists($name) @@ -88,7 +101,7 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf } foreach ($this->loaders as $loader) { - if ($loader instanceof Twig_ExistsLoaderInterface) { + if ($loader instanceof ExistsLoaderInterface) { if ($loader->exists($name)) { return $this->hasSourceCache[$name] = true; } @@ -97,14 +110,14 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf } try { - if ($loader instanceof Twig_SourceContextLoaderInterface) { + if ($loader instanceof SourceContextLoaderInterface) { $loader->getSourceContext($name); } else { $loader->getSource($name); } return $this->hasSourceCache[$name] = true; - } catch (Twig_Error_Loader $e) { + } catch (LoaderError $e) { } } @@ -113,39 +126,39 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf public function getCacheKey($name) { - $exceptions = array(); + $exceptions = []; foreach ($this->loaders as $loader) { - if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { + if ($loader instanceof ExistsLoaderInterface && !$loader->exists($name)) { continue; } try { return $loader->getCacheKey($name); - } catch (Twig_Error_Loader $e) { - $exceptions[] = get_class($loader).': '.$e->getMessage(); + } catch (LoaderError $e) { + $exceptions[] = \get_class($loader).': '.$e->getMessage(); } } - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); + throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); } public function isFresh($name, $time) { - $exceptions = array(); + $exceptions = []; foreach ($this->loaders as $loader) { - if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { + if ($loader instanceof ExistsLoaderInterface && !$loader->exists($name)) { continue; } try { return $loader->isFresh($name, $time); - } catch (Twig_Error_Loader $e) { - $exceptions[] = get_class($loader).': '.$e->getMessage(); + } catch (LoaderError $e) { + $exceptions[] = \get_class($loader).': '.$e->getMessage(); } } - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); + throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); } } -class_alias('Twig_Loader_Chain', 'Twig\Loader\ChainLoader', false); +class_alias('Twig\Loader\ChainLoader', 'Twig_Loader_Chain'); diff --git a/system/libs/Twig/ExistsLoaderInterface.php b/system/libs/Twig/Loader/ExistsLoaderInterface.php old mode 100755 new mode 100644 similarity index 82% rename from system/libs/Twig/ExistsLoaderInterface.php rename to system/libs/Twig/Loader/ExistsLoaderInterface.php index 968cb21a..940d8761 --- a/system/libs/Twig/ExistsLoaderInterface.php +++ b/system/libs/Twig/Loader/ExistsLoaderInterface.php @@ -9,6 +9,8 @@ * file that was distributed with this source code. */ +namespace Twig\Loader; + /** * Adds an exists() method for loaders. * @@ -16,7 +18,7 @@ * * @deprecated since 1.12 (to be removed in 3.0) */ -interface Twig_ExistsLoaderInterface +interface ExistsLoaderInterface { /** * Check if we have the source code of a template, given its name. @@ -28,4 +30,4 @@ interface Twig_ExistsLoaderInterface public function exists($name); } -class_alias('Twig_ExistsLoaderInterface', 'Twig\Loader\ExistsLoaderInterface', false); +class_alias('Twig\Loader\ExistsLoaderInterface', 'Twig_ExistsLoaderInterface'); diff --git a/system/libs/Twig/Loader/Filesystem.php b/system/libs/Twig/Loader/FilesystemLoader.php old mode 100755 new mode 100644 similarity index 65% rename from system/libs/Twig/Loader/Filesystem.php rename to system/libs/Twig/Loader/FilesystemLoader.php index 1275044f..19b43a29 --- a/system/libs/Twig/Loader/Filesystem.php +++ b/system/libs/Twig/Loader/FilesystemLoader.php @@ -9,19 +9,24 @@ * file that was distributed with this source code. */ +namespace Twig\Loader; + +use Twig\Error\LoaderError; +use Twig\Source; + /** * Loads template from the filesystem. * * @author Fabien Potencier */ -class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface +class FilesystemLoader implements LoaderInterface, ExistsLoaderInterface, SourceContextLoaderInterface { /** Identifier of the main namespace. */ const MAIN_NAMESPACE = '__main__'; - protected $paths = array(); - protected $cache = array(); - protected $errorCache = array(); + protected $paths = []; + protected $cache = []; + protected $errorCache = []; private $rootPath; @@ -29,11 +34,11 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI * @param string|array $paths A path or an array of paths where to look for templates * @param string|null $rootPath The root path common to all relative paths (null for getcwd()) */ - public function __construct($paths = array(), $rootPath = null) + public function __construct($paths = [], $rootPath = null) { - $this->rootPath = (null === $rootPath ? getcwd() : $rootPath).DIRECTORY_SEPARATOR; + $this->rootPath = (null === $rootPath ? getcwd() : $rootPath).\DIRECTORY_SEPARATOR; if (false !== $realPath = realpath($rootPath)) { - $this->rootPath = $realPath.DIRECTORY_SEPARATOR; + $this->rootPath = $realPath.\DIRECTORY_SEPARATOR; } if ($paths) { @@ -50,7 +55,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI */ public function getPaths($namespace = self::MAIN_NAMESPACE) { - return isset($this->paths[$namespace]) ? $this->paths[$namespace] : array(); + return isset($this->paths[$namespace]) ? $this->paths[$namespace] : []; } /** @@ -73,11 +78,11 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI */ public function setPaths($paths, $namespace = self::MAIN_NAMESPACE) { - if (!is_array($paths)) { - $paths = array($paths); + if (!\is_array($paths)) { + $paths = [$paths]; } - $this->paths[$namespace] = array(); + $this->paths[$namespace] = []; foreach ($paths as $path) { $this->addPath($path, $namespace); } @@ -89,16 +94,16 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI * @param string $path A path where to look for templates * @param string $namespace A path namespace * - * @throws Twig_Error_Loader + * @throws LoaderError */ public function addPath($path, $namespace = self::MAIN_NAMESPACE) { // invalidate the cache - $this->cache = $this->errorCache = array(); + $this->cache = $this->errorCache = []; $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path; if (!is_dir($checkPath)) { - throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath)); + throw new LoaderError(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath)); } $this->paths[$namespace][] = rtrim($path, '/\\'); @@ -110,16 +115,16 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI * @param string $path A path where to look for templates * @param string $namespace A path namespace * - * @throws Twig_Error_Loader + * @throws LoaderError */ public function prependPath($path, $namespace = self::MAIN_NAMESPACE) { // invalidate the cache - $this->cache = $this->errorCache = array(); + $this->cache = $this->errorCache = []; $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path; if (!is_dir($checkPath)) { - throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath)); + throw new LoaderError(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath)); } $path = rtrim($path, '/\\'); @@ -133,22 +138,30 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI public function getSource($name) { - @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED); + @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', \get_class($this)), E_USER_DEPRECATED); - return file_get_contents($this->findTemplate($name)); + if (null === ($path = $this->findTemplate($name)) || false === $path) { + return ''; + } + + return file_get_contents($path); } public function getSourceContext($name) { - $path = $this->findTemplate($name); + if (null === ($path = $this->findTemplate($name)) || false === $path) { + return new Source('', $name, ''); + } - return new Twig_Source(file_get_contents($path), $name, $path); + return new Source(file_get_contents($path), $name, $path); } public function getCacheKey($name) { - $path = $this->findTemplate($name); - $len = strlen($this->rootPath); + if (null === ($path = $this->findTemplate($name)) || false === $path) { + return ''; + } + $len = \strlen($this->rootPath); if (0 === strncmp($this->rootPath, $path, $len)) { return substr($path, $len); } @@ -165,9 +178,9 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI } try { - return false !== $this->findTemplate($name, false); - } catch (Twig_Error_Loader $exception) { - @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); + return null !== ($path = $this->findTemplate($name, false)) && false !== $path; + } catch (LoaderError $e) { + @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); return false; } @@ -175,12 +188,24 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI public function isFresh($name, $time) { - return filemtime($this->findTemplate($name)) <= $time; + // false support to be removed in 3.0 + if (null === ($path = $this->findTemplate($name)) || false === $path) { + return false; + } + + return filemtime($path) < $time; } + /** + * Checks if the template can be found. + * + * @param string $name The template name + * + * @return string|false|null The template name or false/null + */ protected function findTemplate($name) { - $throw = func_num_args() > 1 ? func_get_arg(1) : true; + $throw = \func_num_args() > 1 ? func_get_arg(1) : true; $name = $this->normalizeName($name); if (isset($this->cache[$name])) { @@ -192,12 +217,20 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI return false; } - throw new Twig_Error_Loader($this->errorCache[$name]); + throw new LoaderError($this->errorCache[$name]); } - $this->validateName($name); + try { + $this->validateName($name); - list($namespace, $shortname) = $this->parseName($name); + list($namespace, $shortname) = $this->parseName($name); + } catch (LoaderError $e) { + if (!$throw) { + return false; + } + + throw $e; + } if (!isset($this->paths[$namespace])) { $this->errorCache[$name] = sprintf('There are no registered paths for namespace "%s".', $namespace); @@ -206,12 +239,12 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI return false; } - throw new Twig_Error_Loader($this->errorCache[$name]); + throw new LoaderError($this->errorCache[$name]); } foreach ($this->paths[$namespace] as $path) { if (!$this->isAbsolutePath($path)) { - $path = $this->rootPath.'/'.$path; + $path = $this->rootPath.$path; } if (is_file($path.'/'.$shortname)) { @@ -229,23 +262,23 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI return false; } - throw new Twig_Error_Loader($this->errorCache[$name]); + throw new LoaderError($this->errorCache[$name]); } protected function parseName($name, $default = self::MAIN_NAMESPACE) { if (isset($name[0]) && '@' == $name[0]) { if (false === $pos = strpos($name, '/')) { - throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name)); + throw new LoaderError(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name)); } $namespace = substr($name, 1, $pos - 1); $shortname = substr($name, $pos + 1); - return array($namespace, $shortname); + return [$namespace, $shortname]; } - return array($default, $name); + return [$default, $name]; } protected function normalizeName($name) @@ -256,7 +289,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI protected function validateName($name) { if (false !== strpos($name, "\0")) { - throw new Twig_Error_Loader('A template name cannot contain NUL bytes.'); + throw new LoaderError('A template name cannot contain NUL bytes.'); } $name = ltrim($name, '/'); @@ -270,7 +303,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI } if ($level < 0) { - throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name)); + throw new LoaderError(sprintf('Looks like you try to load a template outside configured directories (%s).', $name)); } } } @@ -278,8 +311,8 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI private function isAbsolutePath($file) { return strspn($file, '/\\', 0, 1) - || (strlen($file) > 3 && ctype_alpha($file[0]) - && substr($file, 1, 1) === ':' + || (\strlen($file) > 3 && ctype_alpha($file[0]) + && ':' === substr($file, 1, 1) && strspn($file, '/\\', 2, 1) ) || null !== parse_url($file, PHP_URL_SCHEME) @@ -287,4 +320,4 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI } } -class_alias('Twig_Loader_Filesystem', 'Twig\Loader\FilesystemLoader', false); +class_alias('Twig\Loader\FilesystemLoader', 'Twig_Loader_Filesystem'); diff --git a/system/libs/Twig/LoaderInterface.php b/system/libs/Twig/Loader/LoaderInterface.php old mode 100755 new mode 100644 similarity index 78% rename from system/libs/Twig/LoaderInterface.php rename to system/libs/Twig/Loader/LoaderInterface.php index 459a70ab..15be7a88 --- a/system/libs/Twig/LoaderInterface.php +++ b/system/libs/Twig/Loader/LoaderInterface.php @@ -9,12 +9,16 @@ * file that was distributed with this source code. */ +namespace Twig\Loader; + +use Twig\Error\LoaderError; + /** * Interface all loaders must implement. * * @author Fabien Potencier */ -interface Twig_LoaderInterface +interface LoaderInterface { /** * Gets the source code of a template, given its name. @@ -23,9 +27,9 @@ interface Twig_LoaderInterface * * @return string The template source code * - * @throws Twig_Error_Loader When $name is not found + * @throws LoaderError When $name is not found * - * @deprecated since 1.27 (to be removed in 2.0), implement Twig_SourceContextLoaderInterface + * @deprecated since 1.27 (to be removed in 2.0), implement Twig\Loader\SourceContextLoaderInterface */ public function getSource($name); @@ -36,7 +40,7 @@ interface Twig_LoaderInterface * * @return string The cache key * - * @throws Twig_Error_Loader When $name is not found + * @throws LoaderError When $name is not found */ public function getCacheKey($name); @@ -49,9 +53,9 @@ interface Twig_LoaderInterface * * @return bool true if the template is fresh, false otherwise * - * @throws Twig_Error_Loader When $name is not found + * @throws LoaderError When $name is not found */ public function isFresh($name, $time); } -class_alias('Twig_LoaderInterface', 'Twig\Loader\LoaderInterface', false); +class_alias('Twig\Loader\LoaderInterface', 'Twig_LoaderInterface'); diff --git a/system/libs/Twig/SourceContextLoaderInterface.php b/system/libs/Twig/Loader/SourceContextLoaderInterface.php similarity index 67% rename from system/libs/Twig/SourceContextLoaderInterface.php rename to system/libs/Twig/Loader/SourceContextLoaderInterface.php index a6e8c425..78b1fcd4 100644 --- a/system/libs/Twig/SourceContextLoaderInterface.php +++ b/system/libs/Twig/Loader/SourceContextLoaderInterface.php @@ -9,6 +9,11 @@ * file that was distributed with this source code. */ +namespace Twig\Loader; + +use Twig\Error\LoaderError; +use Twig\Source; + /** * Adds a getSourceContext() method for loaders. * @@ -16,18 +21,18 @@ * * @deprecated since 1.27 (to be removed in 3.0) */ -interface Twig_SourceContextLoaderInterface +interface SourceContextLoaderInterface { /** * Returns the source context for a given template logical name. * * @param string $name The template logical name * - * @return Twig_Source + * @return Source * - * @throws Twig_Error_Loader When $name is not found + * @throws LoaderError When $name is not found */ public function getSourceContext($name); } -class_alias('Twig_SourceContextLoaderInterface', 'Twig\Loader\SourceContextLoaderInterface', false); +class_alias('Twig\Loader\SourceContextLoaderInterface', 'Twig_SourceContextLoaderInterface'); diff --git a/system/libs/Twig/Markup.php b/system/libs/Twig/Markup.php index 8591d1f9..107941cd 100755 --- a/system/libs/Twig/Markup.php +++ b/system/libs/Twig/Markup.php @@ -9,12 +9,14 @@ * file that was distributed with this source code. */ +namespace Twig; + /** * Marks a content as safe. * * @author Fabien Potencier */ -class Twig_Markup implements Countable +class Markup implements \Countable { protected $content; protected $charset; @@ -32,8 +34,8 @@ class Twig_Markup implements Countable public function count() { - return function_exists('mb_get_info') ? mb_strlen($this->content, $this->charset) : strlen($this->content); + return \function_exists('mb_get_info') ? mb_strlen($this->content, $this->charset) : \strlen($this->content); } } -class_alias('Twig_Markup', 'Twig\Markup', false); +class_alias('Twig\Markup', 'Twig_Markup'); diff --git a/system/libs/Twig/Node/AutoEscape.php b/system/libs/Twig/Node/AutoEscapeNode.php old mode 100755 new mode 100644 similarity index 59% rename from system/libs/Twig/Node/AutoEscape.php rename to system/libs/Twig/Node/AutoEscapeNode.php index 17e4e381..a9403066 --- a/system/libs/Twig/Node/AutoEscape.php +++ b/system/libs/Twig/Node/AutoEscapeNode.php @@ -9,6 +9,10 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; + /** * Represents an autoescape node. * @@ -20,17 +24,17 @@ * * @author Fabien Potencier */ -class Twig_Node_AutoEscape extends Twig_Node +class AutoEscapeNode extends Node { - public function __construct($value, Twig_NodeInterface $body, $lineno, $tag = 'autoescape') + public function __construct($value, \Twig_NodeInterface $body, $lineno, $tag = 'autoescape') { - parent::__construct(array('body' => $body), array('value' => $value), $lineno, $tag); + parent::__construct(['body' => $body], ['value' => $value], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler->subcompile($this->getNode('body')); } } -class_alias('Twig_Node_AutoEscape', 'Twig\Node\AutoEscapeNode', false); +class_alias('Twig\Node\AutoEscapeNode', 'Twig_Node_AutoEscape'); diff --git a/system/libs/Twig/Node/Block.php b/system/libs/Twig/Node/BlockNode.php old mode 100755 new mode 100644 similarity index 60% rename from system/libs/Twig/Node/Block.php rename to system/libs/Twig/Node/BlockNode.php index 91752ad2..1ffc8ca7 --- a/system/libs/Twig/Node/Block.php +++ b/system/libs/Twig/Node/BlockNode.php @@ -10,23 +10,27 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; + /** * Represents a block node. * * @author Fabien Potencier */ -class Twig_Node_Block extends Twig_Node +class BlockNode extends Node { - public function __construct($name, Twig_NodeInterface $body, $lineno, $tag = null) + public function __construct($name, \Twig_NodeInterface $body, $lineno, $tag = null) { - parent::__construct(array('body' => $body), array('name' => $name), $lineno, $tag); + parent::__construct(['body' => $body], ['name' => $name], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->addDebugInfo($this) - ->write(sprintf("public function block_%s(\$context, array \$blocks = array())\n", $this->getAttribute('name')), "{\n") + ->write(sprintf("public function block_%s(\$context, array \$blocks = [])\n", $this->getAttribute('name')), "{\n") ->indent() ; @@ -38,4 +42,4 @@ class Twig_Node_Block extends Twig_Node } } -class_alias('Twig_Node_Block', 'Twig\Node\BlockNode', false); +class_alias('Twig\Node\BlockNode', 'Twig_Node_Block'); diff --git a/system/libs/Twig/Node/BlockReference.php b/system/libs/Twig/Node/BlockReferenceNode.php old mode 100755 new mode 100644 similarity index 66% rename from system/libs/Twig/Node/BlockReference.php rename to system/libs/Twig/Node/BlockReferenceNode.php index 92a9f398..de069093 --- a/system/libs/Twig/Node/BlockReference.php +++ b/system/libs/Twig/Node/BlockReferenceNode.php @@ -10,19 +10,23 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; + /** * Represents a block call node. * * @author Fabien Potencier */ -class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInterface +class BlockReferenceNode extends Node implements NodeOutputInterface { public function __construct($name, $lineno, $tag = null) { - parent::__construct(array(), array('name' => $name), $lineno, $tag); + parent::__construct([], ['name' => $name], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->addDebugInfo($this) @@ -31,4 +35,4 @@ class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInter } } -class_alias('Twig_Node_BlockReference', 'Twig\Node\BlockReferenceNode', false); +class_alias('Twig\Node\BlockReferenceNode', 'Twig_Node_BlockReference'); diff --git a/system/libs/Twig/Node/Body.php b/system/libs/Twig/Node/BodyNode.php old mode 100755 new mode 100644 similarity index 74% rename from system/libs/Twig/Node/Body.php rename to system/libs/Twig/Node/BodyNode.php index 07dfef8b..5290be56 --- a/system/libs/Twig/Node/Body.php +++ b/system/libs/Twig/Node/BodyNode.php @@ -9,13 +9,15 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + /** * Represents a body node. * * @author Fabien Potencier */ -class Twig_Node_Body extends Twig_Node +class BodyNode extends Node { } -class_alias('Twig_Node_Body', 'Twig\Node\BodyNode', false); +class_alias('Twig\Node\BodyNode', 'Twig_Node_Body'); diff --git a/system/libs/Twig/Node/CheckSecurity.php b/system/libs/Twig/Node/CheckSecurityNode.php old mode 100755 new mode 100644 similarity index 60% rename from system/libs/Twig/Node/CheckSecurity.php rename to system/libs/Twig/Node/CheckSecurityNode.php index 7258acb6..cf0a7a13 --- a/system/libs/Twig/Node/CheckSecurity.php +++ b/system/libs/Twig/Node/CheckSecurityNode.php @@ -9,10 +9,14 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; + /** * @author Fabien Potencier */ -class Twig_Node_CheckSecurity extends Twig_Node +class CheckSecurityNode extends Node { protected $usedFilters; protected $usedTags; @@ -27,12 +31,12 @@ class Twig_Node_CheckSecurity extends Twig_Node parent::__construct(); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { - $tags = $filters = $functions = array(); - foreach (array('tags', 'filters', 'functions') as $type) { + $tags = $filters = $functions = []; + foreach (['tags', 'filters', 'functions'] as $type) { foreach ($this->{'used'.ucfirst($type)} as $name => $node) { - if ($node instanceof Twig_Node) { + if ($node instanceof Node) { ${$type}[$name] = $node->getTemplateLine(); } else { ${$type}[$node] = null; @@ -41,31 +45,32 @@ class Twig_Node_CheckSecurity extends Twig_Node } $compiler + ->write("\$this->sandbox = \$this->env->getExtension('\Twig\Extension\SandboxExtension');\n") ->write('$tags = ')->repr(array_filter($tags))->raw(";\n") ->write('$filters = ')->repr(array_filter($filters))->raw(";\n") ->write('$functions = ')->repr(array_filter($functions))->raw(";\n\n") ->write("try {\n") ->indent() - ->write("\$this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity(\n") + ->write("\$this->sandbox->checkSecurity(\n") ->indent() - ->write(!$tags ? "array(),\n" : "array('".implode("', '", array_keys($tags))."'),\n") - ->write(!$filters ? "array(),\n" : "array('".implode("', '", array_keys($filters))."'),\n") - ->write(!$functions ? "array()\n" : "array('".implode("', '", array_keys($functions))."')\n") + ->write(!$tags ? "[],\n" : "['".implode("', '", array_keys($tags))."'],\n") + ->write(!$filters ? "[],\n" : "['".implode("', '", array_keys($filters))."'],\n") + ->write(!$functions ? "[]\n" : "['".implode("', '", array_keys($functions))."']\n") ->outdent() ->write(");\n") ->outdent() - ->write("} catch (Twig_Sandbox_SecurityError \$e) {\n") + ->write("} catch (SecurityError \$e) {\n") ->indent() ->write("\$e->setSourceContext(\$this->getSourceContext());\n\n") - ->write("if (\$e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset(\$tags[\$e->getTagName()])) {\n") + ->write("if (\$e instanceof SecurityNotAllowedTagError && isset(\$tags[\$e->getTagName()])) {\n") ->indent() ->write("\$e->setTemplateLine(\$tags[\$e->getTagName()]);\n") ->outdent() - ->write("} elseif (\$e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset(\$filters[\$e->getFilterName()])) {\n") + ->write("} elseif (\$e instanceof SecurityNotAllowedFilterError && isset(\$filters[\$e->getFilterName()])) {\n") ->indent() ->write("\$e->setTemplateLine(\$filters[\$e->getFilterName()]);\n") ->outdent() - ->write("} elseif (\$e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset(\$functions[\$e->getFunctionName()])) {\n") + ->write("} elseif (\$e instanceof SecurityNotAllowedFunctionError && isset(\$functions[\$e->getFunctionName()])) {\n") ->indent() ->write("\$e->setTemplateLine(\$functions[\$e->getFunctionName()]);\n") ->outdent() @@ -77,4 +82,4 @@ class Twig_Node_CheckSecurity extends Twig_Node } } -class_alias('Twig_Node_CheckSecurity', 'Twig\Node\CheckSecurityNode', false); +class_alias('Twig\Node\CheckSecurityNode', 'Twig_Node_CheckSecurity'); diff --git a/system/libs/Twig/Node/CheckToStringNode.php b/system/libs/Twig/Node/CheckToStringNode.php new file mode 100644 index 00000000..5d674679 --- /dev/null +++ b/system/libs/Twig/Node/CheckToStringNode.php @@ -0,0 +1,42 @@ + + */ +class CheckToStringNode extends AbstractExpression +{ + public function __construct(AbstractExpression $expr) + { + parent::__construct(['expr' => $expr], [], $expr->getTemplateLine(), $expr->getNodeTag()); + } + + public function compile(Compiler $compiler) + { + $compiler + ->raw('$this->sandbox->ensureToStringAllowed(') + ->subcompile($this->getNode('expr')) + ->raw(')') + ; + } +} diff --git a/system/libs/Twig/Node/DeprecatedNode.php b/system/libs/Twig/Node/DeprecatedNode.php new file mode 100644 index 00000000..62c0dd4b --- /dev/null +++ b/system/libs/Twig/Node/DeprecatedNode.php @@ -0,0 +1,55 @@ + + */ +class DeprecatedNode extends Node +{ + public function __construct(AbstractExpression $expr, $lineno, $tag = null) + { + parent::__construct(['expr' => $expr], [], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler->addDebugInfo($this); + + $expr = $this->getNode('expr'); + + if ($expr instanceof ConstantExpression) { + $compiler->write('@trigger_error(') + ->subcompile($expr); + } else { + $varName = $compiler->getVarName(); + $compiler->write(sprintf('$%s = ', $varName)) + ->subcompile($expr) + ->raw(";\n") + ->write(sprintf('@trigger_error($%s', $varName)); + } + + $compiler + ->raw('.') + ->string(sprintf(' ("%s" at line %d).', $this->getTemplateName(), $this->getTemplateLine())) + ->raw(", E_USER_DEPRECATED);\n") + ; + } +} + +class_alias('Twig\Node\DeprecatedNode', 'Twig_Node_Deprecated'); diff --git a/system/libs/Twig/Node/Do.php b/system/libs/Twig/Node/DoNode.php old mode 100755 new mode 100644 similarity index 57% rename from system/libs/Twig/Node/Do.php rename to system/libs/Twig/Node/DoNode.php index cdd7e77a..80c4cea7 --- a/system/libs/Twig/Node/Do.php +++ b/system/libs/Twig/Node/DoNode.php @@ -9,19 +9,24 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; + /** * Represents a do node. * * @author Fabien Potencier */ -class Twig_Node_Do extends Twig_Node +class DoNode extends Node { - public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) + public function __construct(AbstractExpression $expr, $lineno, $tag = null) { - parent::__construct(array('expr' => $expr), array(), $lineno, $tag); + parent::__construct(['expr' => $expr], [], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->addDebugInfo($this) @@ -32,4 +37,4 @@ class Twig_Node_Do extends Twig_Node } } -class_alias('Twig_Node_Do', 'Twig\Node\DoNode', false); +class_alias('Twig\Node\DoNode', 'Twig_Node_Do'); diff --git a/system/libs/Twig/Node/Embed.php b/system/libs/Twig/Node/EmbedNode.php old mode 100755 new mode 100644 similarity index 64% rename from system/libs/Twig/Node/Embed.php rename to system/libs/Twig/Node/EmbedNode.php index 3785d3a9..05051ece --- a/system/libs/Twig/Node/Embed.php +++ b/system/libs/Twig/Node/EmbedNode.php @@ -9,17 +9,23 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\ConstantExpression; + /** * Represents an embed node. * * @author Fabien Potencier */ -class Twig_Node_Embed extends Twig_Node_Include +class EmbedNode extends IncludeNode { // we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module) - public function __construct($name, $index, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null) + public function __construct($name, $index, AbstractExpression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null) { - parent::__construct(new Twig_Node_Expression_Constant('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag); + parent::__construct(new ConstantExpression('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag); $this->setAttribute('name', $name); // to be removed in 2.0, used name instead @@ -27,7 +33,7 @@ class Twig_Node_Embed extends Twig_Node_Include $this->setAttribute('index', $index); } - protected function addGetTemplate(Twig_Compiler $compiler) + protected function addGetTemplate(Compiler $compiler) { $compiler ->write('$this->loadTemplate(') @@ -43,4 +49,4 @@ class Twig_Node_Embed extends Twig_Node_Include } } -class_alias('Twig_Node_Embed', 'Twig\Node\EmbedNode', false); +class_alias('Twig\Node\EmbedNode', 'Twig_Node_Embed'); diff --git a/system/libs/Twig/Node/Expression.php b/system/libs/Twig/Node/Expression/AbstractExpression.php old mode 100755 new mode 100644 similarity index 66% rename from system/libs/Twig/Node/Expression.php rename to system/libs/Twig/Node/Expression/AbstractExpression.php index a99c4e63..a3528924 --- a/system/libs/Twig/Node/Expression.php +++ b/system/libs/Twig/Node/Expression/AbstractExpression.php @@ -10,13 +10,17 @@ * file that was distributed with this source code. */ +namespace Twig\Node\Expression; + +use Twig\Node\Node; + /** * Abstract class for all nodes that represents an expression. * * @author Fabien Potencier */ -abstract class Twig_Node_Expression extends Twig_Node +abstract class AbstractExpression extends Node { } -class_alias('Twig_Node_Expression', 'Twig\Node\Expression\AbstractExpression', false); +class_alias('Twig\Node\Expression\AbstractExpression', 'Twig_Node_Expression'); diff --git a/system/libs/Twig/Node/Expression/Array.php b/system/libs/Twig/Node/Expression/ArrayExpression.php old mode 100755 new mode 100644 similarity index 64% rename from system/libs/Twig/Node/Expression/Array.php rename to system/libs/Twig/Node/Expression/ArrayExpression.php index 0e77bb08..cd63f934 --- a/system/libs/Twig/Node/Expression/Array.php +++ b/system/libs/Twig/Node/Expression/ArrayExpression.php @@ -8,17 +8,22 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Array extends Twig_Node_Expression + +namespace Twig\Node\Expression; + +use Twig\Compiler; + +class ArrayExpression extends AbstractExpression { protected $index; public function __construct(array $elements, $lineno) { - parent::__construct($elements, array(), $lineno); + parent::__construct($elements, [], $lineno); $this->index = -1; foreach ($this->getKeyValuePairs() as $pair) { - if ($pair['key'] instanceof Twig_Node_Expression_Constant && ctype_digit((string) $pair['key']->getAttribute('value')) && $pair['key']->getAttribute('value') > $this->index) { + if ($pair['key'] instanceof ConstantExpression && ctype_digit((string) $pair['key']->getAttribute('value')) && $pair['key']->getAttribute('value') > $this->index) { $this->index = $pair['key']->getAttribute('value'); } } @@ -26,19 +31,19 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression public function getKeyValuePairs() { - $pairs = array(); + $pairs = []; foreach (array_chunk($this->nodes, 2) as $pair) { - $pairs[] = array( + $pairs[] = [ 'key' => $pair[0], 'value' => $pair[1], - ); + ]; } return $pairs; } - public function hasElement(Twig_Node_Expression $key) + public function hasElement(AbstractExpression $key) { foreach ($this->getKeyValuePairs() as $pair) { // we compare the string representation of the keys @@ -51,18 +56,18 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression return false; } - public function addElement(Twig_Node_Expression $value, Twig_Node_Expression $key = null) + public function addElement(AbstractExpression $value, AbstractExpression $key = null) { if (null === $key) { - $key = new Twig_Node_Expression_Constant(++$this->index, $value->getTemplateLine()); + $key = new ConstantExpression(++$this->index, $value->getTemplateLine()); } array_push($this->nodes, $key, $value); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { - $compiler->raw('array('); + $compiler->raw('['); $first = true; foreach ($this->getKeyValuePairs() as $pair) { if (!$first) { @@ -76,8 +81,8 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression ->subcompile($pair['value']) ; } - $compiler->raw(')'); + $compiler->raw(']'); } } -class_alias('Twig_Node_Expression_Array', 'Twig\Node\Expression\ArrayExpression', false); +class_alias('Twig\Node\Expression\ArrayExpression', 'Twig_Node_Expression_Array'); diff --git a/system/libs/Twig/Node/Expression/ArrowFunctionExpression.php b/system/libs/Twig/Node/Expression/ArrowFunctionExpression.php new file mode 100644 index 00000000..36b77da8 --- /dev/null +++ b/system/libs/Twig/Node/Expression/ArrowFunctionExpression.php @@ -0,0 +1,64 @@ + + */ +class ArrowFunctionExpression extends AbstractExpression +{ + public function __construct(AbstractExpression $expr, Node $names, $lineno, $tag = null) + { + parent::__construct(['expr' => $expr, 'names' => $names], [], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->raw('function (') + ; + foreach ($this->getNode('names') as $i => $name) { + if ($i) { + $compiler->raw(', '); + } + + $compiler + ->raw('$__') + ->raw($name->getAttribute('name')) + ->raw('__') + ; + } + $compiler + ->raw(') use ($context) { ') + ; + foreach ($this->getNode('names') as $name) { + $compiler + ->raw('$context["') + ->raw($name->getAttribute('name')) + ->raw('"] = $__') + ->raw($name->getAttribute('name')) + ->raw('__; ') + ; + } + $compiler + ->raw('return ') + ->subcompile($this->getNode('expr')) + ->raw('; }') + ; + } +} diff --git a/system/libs/Twig/Node/Expression/AssignName.php b/system/libs/Twig/Node/Expression/AssignNameExpression.php old mode 100755 new mode 100644 similarity index 60% rename from system/libs/Twig/Node/Expression/AssignName.php rename to system/libs/Twig/Node/Expression/AssignNameExpression.php index 2e6b4c7c..62c4ac0b --- a/system/libs/Twig/Node/Expression/AssignName.php +++ b/system/libs/Twig/Node/Expression/AssignNameExpression.php @@ -10,9 +10,13 @@ * file that was distributed with this source code. */ -class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name +namespace Twig\Node\Expression; + +use Twig\Compiler; + +class AssignNameExpression extends NameExpression { - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->raw('$context[') @@ -22,4 +26,4 @@ class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name } } -class_alias('Twig_Node_Expression_AssignName', 'Twig\Node\Expression\AssignNameExpression', false); +class_alias('Twig\Node\Expression\AssignNameExpression', 'Twig_Node_Expression_AssignName'); diff --git a/system/libs/Twig/Node/Expression/Binary.php b/system/libs/Twig/Node/Expression/Binary/AbstractBinary.php old mode 100755 new mode 100644 similarity index 50% rename from system/libs/Twig/Node/Expression/Binary.php rename to system/libs/Twig/Node/Expression/Binary/AbstractBinary.php index 2b545d98..0600aeed --- a/system/libs/Twig/Node/Expression/Binary.php +++ b/system/libs/Twig/Node/Expression/Binary/AbstractBinary.php @@ -9,14 +9,20 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; + +abstract class AbstractBinary extends AbstractExpression { - public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno) + public function __construct(\Twig_NodeInterface $left, \Twig_NodeInterface $right, $lineno) { - parent::__construct(array('left' => $left, 'right' => $right), array(), $lineno); + parent::__construct(['left' => $left, 'right' => $right], [], $lineno); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->raw('(') @@ -31,7 +37,7 @@ abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression ; } - abstract public function operator(Twig_Compiler $compiler); + abstract public function operator(Compiler $compiler); } -class_alias('Twig_Node_Expression_Binary', 'Twig\Node\Expression\Binary\AbstractBinary', false); +class_alias('Twig\Node\Expression\Binary\AbstractBinary', 'Twig_Node_Expression_Binary'); diff --git a/system/libs/Twig/Node/Expression/Binary/Add.php b/system/libs/Twig/Node/Expression/Binary/AddBinary.php old mode 100755 new mode 100644 similarity index 53% rename from system/libs/Twig/Node/Expression/Binary/Add.php rename to system/libs/Twig/Node/Expression/Binary/AddBinary.php index 5a09d836..f7719a19 --- a/system/libs/Twig/Node/Expression/Binary/Add.php +++ b/system/libs/Twig/Node/Expression/Binary/AddBinary.php @@ -9,12 +9,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_Add extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class AddBinary extends AbstractBinary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('+'); } } -class_alias('Twig_Node_Expression_Binary_Add', 'Twig\Node\Expression\Binary\AddBinary', false); +class_alias('Twig\Node\Expression\Binary\AddBinary', 'Twig_Node_Expression_Binary_Add'); diff --git a/system/libs/Twig/Node/Expression/Binary/And.php b/system/libs/Twig/Node/Expression/Binary/AndBinary.php old mode 100755 new mode 100644 similarity index 53% rename from system/libs/Twig/Node/Expression/Binary/And.php rename to system/libs/Twig/Node/Expression/Binary/AndBinary.php index 9ffddce6..484597da --- a/system/libs/Twig/Node/Expression/Binary/And.php +++ b/system/libs/Twig/Node/Expression/Binary/AndBinary.php @@ -9,12 +9,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_And extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class AndBinary extends AbstractBinary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('&&'); } } -class_alias('Twig_Node_Expression_Binary_And', 'Twig\Node\Expression\Binary\AndBinary', false); +class_alias('Twig\Node\Expression\Binary\AndBinary', 'Twig_Node_Expression_Binary_And'); diff --git a/system/libs/Twig/Node/Expression/Binary/BitwiseAnd.php b/system/libs/Twig/Node/Expression/Binary/BitwiseAndBinary.php old mode 100755 new mode 100644 similarity index 51% rename from system/libs/Twig/Node/Expression/Binary/BitwiseAnd.php rename to system/libs/Twig/Node/Expression/Binary/BitwiseAndBinary.php index e46e9ebf..cf286912 --- a/system/libs/Twig/Node/Expression/Binary/BitwiseAnd.php +++ b/system/libs/Twig/Node/Expression/Binary/BitwiseAndBinary.php @@ -9,12 +9,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_BitwiseAnd extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class BitwiseAndBinary extends AbstractBinary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('&'); } } -class_alias('Twig_Node_Expression_Binary_BitwiseAnd', 'Twig\Node\Expression\Binary\BitwiseAndBinary', false); +class_alias('Twig\Node\Expression\Binary\BitwiseAndBinary', 'Twig_Node_Expression_Binary_BitwiseAnd'); diff --git a/system/libs/Twig/Node/Expression/Binary/BitwiseOr.php b/system/libs/Twig/Node/Expression/Binary/BitwiseOrBinary.php old mode 100755 new mode 100644 similarity index 51% rename from system/libs/Twig/Node/Expression/Binary/BitwiseOr.php rename to system/libs/Twig/Node/Expression/Binary/BitwiseOrBinary.php index 5d7f1b7c..7d5d2600 --- a/system/libs/Twig/Node/Expression/Binary/BitwiseOr.php +++ b/system/libs/Twig/Node/Expression/Binary/BitwiseOrBinary.php @@ -9,12 +9,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_BitwiseOr extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class BitwiseOrBinary extends AbstractBinary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('|'); } } -class_alias('Twig_Node_Expression_Binary_BitwiseOr', 'Twig\Node\Expression\Binary\BitwiseOrBinary', false); +class_alias('Twig\Node\Expression\Binary\BitwiseOrBinary', 'Twig_Node_Expression_Binary_BitwiseOr'); diff --git a/system/libs/Twig/Node/Expression/Binary/BitwiseXor.php b/system/libs/Twig/Node/Expression/Binary/BitwiseXorBinary.php old mode 100755 new mode 100644 similarity index 51% rename from system/libs/Twig/Node/Expression/Binary/BitwiseXor.php rename to system/libs/Twig/Node/Expression/Binary/BitwiseXorBinary.php index 82edf516..72919871 --- a/system/libs/Twig/Node/Expression/Binary/BitwiseXor.php +++ b/system/libs/Twig/Node/Expression/Binary/BitwiseXorBinary.php @@ -9,12 +9,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_BitwiseXor extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class BitwiseXorBinary extends AbstractBinary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('^'); } } -class_alias('Twig_Node_Expression_Binary_BitwiseXor', 'Twig\Node\Expression\Binary\BitwiseXorBinary', false); +class_alias('Twig\Node\Expression\Binary\BitwiseXorBinary', 'Twig_Node_Expression_Binary_BitwiseXor'); diff --git a/system/libs/Twig/Node/Expression/Binary/Concat.php b/system/libs/Twig/Node/Expression/Binary/ConcatBinary.php old mode 100755 new mode 100644 similarity index 52% rename from system/libs/Twig/Node/Expression/Binary/Concat.php rename to system/libs/Twig/Node/Expression/Binary/ConcatBinary.php index 91abca60..f6e5938f --- a/system/libs/Twig/Node/Expression/Binary/Concat.php +++ b/system/libs/Twig/Node/Expression/Binary/ConcatBinary.php @@ -9,12 +9,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_Concat extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class ConcatBinary extends AbstractBinary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('.'); } } -class_alias('Twig_Node_Expression_Binary_Concat', 'Twig\Node\Expression\Binary\ConcatBinary', false); +class_alias('Twig\Node\Expression\Binary\ConcatBinary', 'Twig_Node_Expression_Binary_Concat'); diff --git a/system/libs/Twig/Node/Expression/Binary/Div.php b/system/libs/Twig/Node/Expression/Binary/DivBinary.php old mode 100755 new mode 100644 similarity index 53% rename from system/libs/Twig/Node/Expression/Binary/Div.php rename to system/libs/Twig/Node/Expression/Binary/DivBinary.php index 38ffa30c..ebfcc758 --- a/system/libs/Twig/Node/Expression/Binary/Div.php +++ b/system/libs/Twig/Node/Expression/Binary/DivBinary.php @@ -9,12 +9,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_Div extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class DivBinary extends AbstractBinary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('/'); } } -class_alias('Twig_Node_Expression_Binary_Div', 'Twig\Node\Expression\Binary\DivBinary', false); +class_alias('Twig\Node\Expression\Binary\DivBinary', 'Twig_Node_Expression_Binary_Div'); diff --git a/system/libs/Twig/Node/Expression/Binary/EndsWith.php b/system/libs/Twig/Node/Expression/Binary/EndsWithBinary.php old mode 100755 new mode 100644 similarity index 69% rename from system/libs/Twig/Node/Expression/Binary/EndsWith.php rename to system/libs/Twig/Node/Expression/Binary/EndsWithBinary.php index 85c52937..41a0065b --- a/system/libs/Twig/Node/Expression/Binary/EndsWith.php +++ b/system/libs/Twig/Node/Expression/Binary/EndsWithBinary.php @@ -8,9 +8,14 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_EndsWith extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class EndsWithBinary extends AbstractBinary { - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $left = $compiler->getVarName(); $right = $compiler->getVarName(); @@ -23,10 +28,10 @@ class Twig_Node_Expression_Binary_EndsWith extends Twig_Node_Expression_Binary ; } - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw(''); } } -class_alias('Twig_Node_Expression_Binary_EndsWith', 'Twig\Node\Expression\Binary\EndsWithBinary', false); +class_alias('Twig\Node\Expression\Binary\EndsWithBinary', 'Twig_Node_Expression_Binary_EndsWith'); diff --git a/system/libs/Twig/Node/Expression/Binary/Equal.php b/system/libs/Twig/Node/Expression/Binary/EqualBinary.php old mode 100755 new mode 100644 similarity index 51% rename from system/libs/Twig/Node/Expression/Binary/Equal.php rename to system/libs/Twig/Node/Expression/Binary/EqualBinary.php index a6a6946b..84904c36 --- a/system/libs/Twig/Node/Expression/Binary/Equal.php +++ b/system/libs/Twig/Node/Expression/Binary/EqualBinary.php @@ -8,12 +8,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_Equal extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class EqualBinary extends AbstractBinary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('=='); } } -class_alias('Twig_Node_Expression_Binary_Equal', 'Twig\Node\Expression\Binary\EqualBinary', false); +class_alias('Twig\Node\Expression\Binary\EqualBinary', 'Twig_Node_Expression_Binary_Equal'); diff --git a/system/libs/Twig/Node/Expression/Binary/FloorDiv.php b/system/libs/Twig/Node/Expression/Binary/FloorDivBinary.php old mode 100755 new mode 100644 similarity index 55% rename from system/libs/Twig/Node/Expression/Binary/FloorDiv.php rename to system/libs/Twig/Node/Expression/Binary/FloorDivBinary.php index 7393bcb8..4dd5e3d3 --- a/system/libs/Twig/Node/Expression/Binary/FloorDiv.php +++ b/system/libs/Twig/Node/Expression/Binary/FloorDivBinary.php @@ -8,19 +8,24 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_FloorDiv extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class FloorDivBinary extends AbstractBinary { - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler->raw('(int) floor('); parent::compile($compiler); $compiler->raw(')'); } - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('/'); } } -class_alias('Twig_Node_Expression_Binary_FloorDiv', 'Twig\Node\Expression\Binary\FloorDivBinary', false); +class_alias('Twig\Node\Expression\Binary\FloorDivBinary', 'Twig_Node_Expression_Binary_FloorDiv'); diff --git a/system/libs/Twig/Node/Expression/Binary/Greater.php b/system/libs/Twig/Node/Expression/Binary/GreaterBinary.php old mode 100755 new mode 100644 similarity index 50% rename from system/libs/Twig/Node/Expression/Binary/Greater.php rename to system/libs/Twig/Node/Expression/Binary/GreaterBinary.php index 832f9797..be73001e --- a/system/libs/Twig/Node/Expression/Binary/Greater.php +++ b/system/libs/Twig/Node/Expression/Binary/GreaterBinary.php @@ -8,12 +8,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_Greater extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class GreaterBinary extends AbstractBinary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('>'); } } -class_alias('Twig_Node_Expression_Binary_Greater', 'Twig\Node\Expression\Binary\GreaterBinary', false); +class_alias('Twig\Node\Expression\Binary\GreaterBinary', 'Twig_Node_Expression_Binary_Greater'); diff --git a/system/libs/Twig/Node/Expression/Binary/GreaterEqual.php b/system/libs/Twig/Node/Expression/Binary/GreaterEqual.php deleted file mode 100755 index c5f76245..00000000 --- a/system/libs/Twig/Node/Expression/Binary/GreaterEqual.php +++ /dev/null @@ -1,19 +0,0 @@ -raw('>='); - } -} - -class_alias('Twig_Node_Expression_Binary_GreaterEqual', 'Twig\Node\Expression\Binary\GreaterEqualBinary', false); diff --git a/system/libs/Twig/Node/Expression/Binary/GreaterEqualBinary.php b/system/libs/Twig/Node/Expression/Binary/GreaterEqualBinary.php new file mode 100644 index 00000000..5c2ae72e --- /dev/null +++ b/system/libs/Twig/Node/Expression/Binary/GreaterEqualBinary.php @@ -0,0 +1,24 @@ +raw('>='); + } +} + +class_alias('Twig\Node\Expression\Binary\GreaterEqualBinary', 'Twig_Node_Expression_Binary_GreaterEqual'); diff --git a/system/libs/Twig/Node/Expression/Binary/In.php b/system/libs/Twig/Node/Expression/Binary/InBinary.php old mode 100755 new mode 100644 similarity index 62% rename from system/libs/Twig/Node/Expression/Binary/In.php rename to system/libs/Twig/Node/Expression/Binary/InBinary.php index af112448..f00b2306 --- a/system/libs/Twig/Node/Expression/Binary/In.php +++ b/system/libs/Twig/Node/Expression/Binary/InBinary.php @@ -8,9 +8,14 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class InBinary extends AbstractBinary { - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->raw('twig_in_filter(') @@ -21,10 +26,10 @@ class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary ; } - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('in'); } } -class_alias('Twig_Node_Expression_Binary_In', 'Twig\Node\Expression\Binary\InBinary', false); +class_alias('Twig\Node\Expression\Binary\InBinary', 'Twig_Node_Expression_Binary_In'); diff --git a/system/libs/Twig/Node/Expression/Binary/Less.php b/system/libs/Twig/Node/Expression/Binary/LessBinary.php old mode 100755 new mode 100644 similarity index 51% rename from system/libs/Twig/Node/Expression/Binary/Less.php rename to system/libs/Twig/Node/Expression/Binary/LessBinary.php index ab8fc1f9..2b202daa --- a/system/libs/Twig/Node/Expression/Binary/Less.php +++ b/system/libs/Twig/Node/Expression/Binary/LessBinary.php @@ -8,12 +8,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_Less extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class LessBinary extends AbstractBinary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('<'); } } -class_alias('Twig_Node_Expression_Binary_Less', 'Twig\Node\Expression\Binary\LessBinary', false); +class_alias('Twig\Node\Expression\Binary\LessBinary', 'Twig_Node_Expression_Binary_Less'); diff --git a/system/libs/Twig/Node/Expression/Binary/LessEqual.php b/system/libs/Twig/Node/Expression/Binary/LessEqual.php deleted file mode 100755 index 71a279e9..00000000 --- a/system/libs/Twig/Node/Expression/Binary/LessEqual.php +++ /dev/null @@ -1,19 +0,0 @@ -raw('<='); - } -} - -class_alias('Twig_Node_Expression_Binary_LessEqual', 'Twig\Node\Expression\Binary\LessEqualBinary', false); diff --git a/system/libs/Twig/Node/Expression/Binary/LessEqualBinary.php b/system/libs/Twig/Node/Expression/Binary/LessEqualBinary.php new file mode 100644 index 00000000..4fffafea --- /dev/null +++ b/system/libs/Twig/Node/Expression/Binary/LessEqualBinary.php @@ -0,0 +1,24 @@ +raw('<='); + } +} + +class_alias('Twig\Node\Expression\Binary\LessEqualBinary', 'Twig_Node_Expression_Binary_LessEqual'); diff --git a/system/libs/Twig/Node/Expression/Binary/Matches.php b/system/libs/Twig/Node/Expression/Binary/MatchesBinary.php old mode 100755 new mode 100644 similarity index 61% rename from system/libs/Twig/Node/Expression/Binary/Matches.php rename to system/libs/Twig/Node/Expression/Binary/MatchesBinary.php index 5cb85584..ae810b26 --- a/system/libs/Twig/Node/Expression/Binary/Matches.php +++ b/system/libs/Twig/Node/Expression/Binary/MatchesBinary.php @@ -8,9 +8,14 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_Matches extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class MatchesBinary extends AbstractBinary { - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->raw('preg_match(') @@ -21,10 +26,10 @@ class Twig_Node_Expression_Binary_Matches extends Twig_Node_Expression_Binary ; } - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw(''); } } -class_alias('Twig_Node_Expression_Binary_Matches', 'Twig\Node\Expression\Binary\MatchesBinary', false); +class_alias('Twig\Node\Expression\Binary\MatchesBinary', 'Twig_Node_Expression_Binary_Matches'); diff --git a/system/libs/Twig/Node/Expression/Binary/Mod.php b/system/libs/Twig/Node/Expression/Binary/ModBinary.php old mode 100755 new mode 100644 similarity index 53% rename from system/libs/Twig/Node/Expression/Binary/Mod.php rename to system/libs/Twig/Node/Expression/Binary/ModBinary.php index 28109633..e6a2b360 --- a/system/libs/Twig/Node/Expression/Binary/Mod.php +++ b/system/libs/Twig/Node/Expression/Binary/ModBinary.php @@ -9,12 +9,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_Mod extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class ModBinary extends AbstractBinary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('%'); } } -class_alias('Twig_Node_Expression_Binary_Mod', 'Twig\Node\Expression\Binary\ModBinary', false); +class_alias('Twig\Node\Expression\Binary\ModBinary', 'Twig_Node_Expression_Binary_Mod'); diff --git a/system/libs/Twig/Node/Expression/Binary/Mul.php b/system/libs/Twig/Node/Expression/Binary/MulBinary.php old mode 100755 new mode 100644 similarity index 53% rename from system/libs/Twig/Node/Expression/Binary/Mul.php rename to system/libs/Twig/Node/Expression/Binary/MulBinary.php index 790c6a22..cd65f5df --- a/system/libs/Twig/Node/Expression/Binary/Mul.php +++ b/system/libs/Twig/Node/Expression/Binary/MulBinary.php @@ -9,12 +9,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_Mul extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class MulBinary extends AbstractBinary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('*'); } } -class_alias('Twig_Node_Expression_Binary_Mul', 'Twig\Node\Expression\Binary\MulBinary', false); +class_alias('Twig\Node\Expression\Binary\MulBinary', 'Twig_Node_Expression_Binary_Mul'); diff --git a/system/libs/Twig/Node/Expression/Binary/NotEqual.php b/system/libs/Twig/Node/Expression/Binary/NotEqualBinary.php old mode 100755 new mode 100644 similarity index 50% rename from system/libs/Twig/Node/Expression/Binary/NotEqual.php rename to system/libs/Twig/Node/Expression/Binary/NotEqualBinary.php index bb45c9ed..df5c6a23 --- a/system/libs/Twig/Node/Expression/Binary/NotEqual.php +++ b/system/libs/Twig/Node/Expression/Binary/NotEqualBinary.php @@ -8,12 +8,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_NotEqual extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class NotEqualBinary extends AbstractBinary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('!='); } } -class_alias('Twig_Node_Expression_Binary_NotEqual', 'Twig\Node\Expression\Binary\NotEqualBinary', false); +class_alias('Twig\Node\Expression\Binary\NotEqualBinary', 'Twig_Node_Expression_Binary_NotEqual'); diff --git a/system/libs/Twig/Node/Expression/Binary/NotIn.php b/system/libs/Twig/Node/Expression/Binary/NotInBinary.php old mode 100755 new mode 100644 similarity index 62% rename from system/libs/Twig/Node/Expression/Binary/NotIn.php rename to system/libs/Twig/Node/Expression/Binary/NotInBinary.php index 9dedf92f..ed2034e3 --- a/system/libs/Twig/Node/Expression/Binary/NotIn.php +++ b/system/libs/Twig/Node/Expression/Binary/NotInBinary.php @@ -8,9 +8,14 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class NotInBinary extends AbstractBinary { - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->raw('!twig_in_filter(') @@ -21,10 +26,10 @@ class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary ; } - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('not in'); } } -class_alias('Twig_Node_Expression_Binary_NotIn', 'Twig\Node\Expression\Binary\NotInBinary', false); +class_alias('Twig\Node\Expression\Binary\NotInBinary', 'Twig_Node_Expression_Binary_NotIn'); diff --git a/system/libs/Twig/Node/Expression/Binary/Or.php b/system/libs/Twig/Node/Expression/Binary/OrBinary.php old mode 100755 new mode 100644 similarity index 54% rename from system/libs/Twig/Node/Expression/Binary/Or.php rename to system/libs/Twig/Node/Expression/Binary/OrBinary.php index dc9eece1..8f9da431 --- a/system/libs/Twig/Node/Expression/Binary/Or.php +++ b/system/libs/Twig/Node/Expression/Binary/OrBinary.php @@ -9,12 +9,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_Or extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class OrBinary extends AbstractBinary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('||'); } } -class_alias('Twig_Node_Expression_Binary_Or', 'Twig\Node\Expression\Binary\OrBinary', false); +class_alias('Twig\Node\Expression\Binary\OrBinary', 'Twig_Node_Expression_Binary_Or'); diff --git a/system/libs/Twig/Node/Expression/Binary/Power.php b/system/libs/Twig/Node/Expression/Binary/PowerBinary.php old mode 100755 new mode 100644 similarity index 61% rename from system/libs/Twig/Node/Expression/Binary/Power.php rename to system/libs/Twig/Node/Expression/Binary/PowerBinary.php index d24777bd..10a8d94c --- a/system/libs/Twig/Node/Expression/Binary/Power.php +++ b/system/libs/Twig/Node/Expression/Binary/PowerBinary.php @@ -8,11 +8,16 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class PowerBinary extends AbstractBinary { - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { - if (PHP_VERSION_ID >= 50600) { + if (\PHP_VERSION_ID >= 50600) { return parent::compile($compiler); } @@ -25,10 +30,10 @@ class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary ; } - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('**'); } } -class_alias('Twig_Node_Expression_Binary_Power', 'Twig\Node\Expression\Binary\PowerBinary', false); +class_alias('Twig\Node\Expression\Binary\PowerBinary', 'Twig_Node_Expression_Binary_Power'); diff --git a/system/libs/Twig/Node/Expression/Binary/Range.php b/system/libs/Twig/Node/Expression/Binary/RangeBinary.php old mode 100755 new mode 100644 similarity index 61% rename from system/libs/Twig/Node/Expression/Binary/Range.php rename to system/libs/Twig/Node/Expression/Binary/RangeBinary.php index 187f6765..e9c0cdf5 --- a/system/libs/Twig/Node/Expression/Binary/Range.php +++ b/system/libs/Twig/Node/Expression/Binary/RangeBinary.php @@ -8,9 +8,14 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class RangeBinary extends AbstractBinary { - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->raw('range(') @@ -21,10 +26,10 @@ class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary ; } - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('..'); } } -class_alias('Twig_Node_Expression_Binary_Range', 'Twig\Node\Expression\Binary\RangeBinary', false); +class_alias('Twig\Node\Expression\Binary\RangeBinary', 'Twig_Node_Expression_Binary_Range'); diff --git a/system/libs/Twig/Node/Expression/Binary/StartsWith.php b/system/libs/Twig/Node/Expression/Binary/StartsWithBinary.php old mode 100755 new mode 100644 similarity index 69% rename from system/libs/Twig/Node/Expression/Binary/StartsWith.php rename to system/libs/Twig/Node/Expression/Binary/StartsWithBinary.php index 7e43b8de..1fe59fb4 --- a/system/libs/Twig/Node/Expression/Binary/StartsWith.php +++ b/system/libs/Twig/Node/Expression/Binary/StartsWithBinary.php @@ -8,9 +8,14 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_StartsWith extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class StartsWithBinary extends AbstractBinary { - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $left = $compiler->getVarName(); $right = $compiler->getVarName(); @@ -23,10 +28,10 @@ class Twig_Node_Expression_Binary_StartsWith extends Twig_Node_Expression_Binary ; } - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw(''); } } -class_alias('Twig_Node_Expression_Binary_StartsWith', 'Twig\Node\Expression\Binary\StartsWithBinary', false); +class_alias('Twig\Node\Expression\Binary\StartsWithBinary', 'Twig_Node_Expression_Binary_StartsWith'); diff --git a/system/libs/Twig/Node/Expression/Binary/Sub.php b/system/libs/Twig/Node/Expression/Binary/SubBinary.php old mode 100755 new mode 100644 similarity index 53% rename from system/libs/Twig/Node/Expression/Binary/Sub.php rename to system/libs/Twig/Node/Expression/Binary/SubBinary.php index cff8ed07..25469750 --- a/system/libs/Twig/Node/Expression/Binary/Sub.php +++ b/system/libs/Twig/Node/Expression/Binary/SubBinary.php @@ -9,12 +9,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Binary_Sub extends Twig_Node_Expression_Binary + +namespace Twig\Node\Expression\Binary; + +use Twig\Compiler; + +class SubBinary extends AbstractBinary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { return $compiler->raw('-'); } } -class_alias('Twig_Node_Expression_Binary_Sub', 'Twig\Node\Expression\Binary\SubBinary', false); +class_alias('Twig\Node\Expression\Binary\SubBinary', 'Twig_Node_Expression_Binary_Sub'); diff --git a/system/libs/Twig/Node/Expression/BlockReference.php b/system/libs/Twig/Node/Expression/BlockReferenceExpression.php old mode 100755 new mode 100644 similarity index 73% rename from system/libs/Twig/Node/Expression/BlockReference.php rename to system/libs/Twig/Node/Expression/BlockReferenceExpression.php index 37a3983d..0a56849c --- a/system/libs/Twig/Node/Expression/BlockReference.php +++ b/system/libs/Twig/Node/Expression/BlockReferenceExpression.php @@ -10,33 +10,38 @@ * file that was distributed with this source code. */ +namespace Twig\Node\Expression; + +use Twig\Compiler; +use Twig\Node\Node; + /** * Represents a block call node. * * @author Fabien Potencier */ -class Twig_Node_Expression_BlockReference extends Twig_Node_Expression +class BlockReferenceExpression extends AbstractExpression { /** - * @param Twig_Node|null $template + * @param Node|null $template */ - public function __construct(Twig_NodeInterface $name, $template = null, $lineno, $tag = null) + public function __construct(\Twig_NodeInterface $name, $template = null, $lineno, $tag = null) { - if (is_bool($template)) { + if (\is_bool($template)) { @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); $template = null; } - $nodes = array('name' => $name); + $nodes = ['name' => $name]; if (null !== $template) { $nodes['template'] = $template; } - parent::__construct($nodes, array('is_defined_test' => false, 'output' => false), $lineno, $tag); + parent::__construct($nodes, ['is_defined_test' => false, 'output' => false], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { if ($this->getAttribute('is_defined_test')) { $this->compileTemplateCall($compiler, 'hasBlock'); @@ -53,7 +58,7 @@ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression } } - private function compileTemplateCall(Twig_Compiler $compiler, $method) + private function compileTemplateCall(Compiler $compiler, $method) { if (!$this->hasNode('template')) { $compiler->write('$this'); @@ -75,7 +80,7 @@ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression return $compiler; } - private function compileBlockArguments(Twig_Compiler $compiler) + private function compileBlockArguments(Compiler $compiler) { $compiler ->raw('(') @@ -90,4 +95,4 @@ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression } } -class_alias('Twig_Node_Expression_BlockReference', 'Twig\Node\Expression\BlockReferenceExpression', false); +class_alias('Twig\Node\Expression\BlockReferenceExpression', 'Twig_Node_Expression_BlockReference'); diff --git a/system/libs/Twig/Node/Expression/Call.php b/system/libs/Twig/Node/Expression/CallExpression.php old mode 100755 new mode 100644 similarity index 63% rename from system/libs/Twig/Node/Expression/Call.php rename to system/libs/Twig/Node/Expression/CallExpression.php index d962b6a5..d202a739 --- a/system/libs/Twig/Node/Expression/Call.php +++ b/system/libs/Twig/Node/Expression/CallExpression.php @@ -8,46 +8,56 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -abstract class Twig_Node_Expression_Call extends Twig_Node_Expression + +namespace Twig\Node\Expression; + +use Twig\Compiler; +use Twig\Error\SyntaxError; +use Twig\Extension\ExtensionInterface; +use Twig\Node\Node; + +abstract class CallExpression extends AbstractExpression { private $reflector; - protected function compileCallable(Twig_Compiler $compiler) + protected function compileCallable(Compiler $compiler) { $closingParenthesis = false; + $isArray = false; if ($this->hasAttribute('callable') && $callable = $this->getAttribute('callable')) { - if (is_string($callable) && false === strpos($callable, '::')) { + if (\is_string($callable) && false === strpos($callable, '::')) { $compiler->raw($callable); } else { list($r, $callable) = $this->reflectCallable($callable); - if ($r instanceof ReflectionMethod && is_string($callable[0])) { + if ($r instanceof \ReflectionMethod && \is_string($callable[0])) { if ($r->isStatic()) { $compiler->raw(sprintf('%s::%s', $callable[0], $callable[1])); } else { $compiler->raw(sprintf('$this->env->getRuntime(\'%s\')->%s', $callable[0], $callable[1])); } - } elseif ($r instanceof ReflectionMethod && $callable[0] instanceof Twig_ExtensionInterface) { - $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', get_class($callable[0]), $callable[1])); + } elseif ($r instanceof \ReflectionMethod && $callable[0] instanceof ExtensionInterface) { + $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', \get_class($callable[0]), $callable[1])); } else { $type = ucfirst($this->getAttribute('type')); - $compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name'))); + $compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), ', $type, $this->getAttribute('name'))); $closingParenthesis = true; + $isArray = true; } } } else { $compiler->raw($this->getAttribute('thing')->compile()); } - $this->compileArguments($compiler); + $this->compileArguments($compiler, $isArray); if ($closingParenthesis) { $compiler->raw(')'); } } - protected function compileArguments(Twig_Compiler $compiler) + protected function compileArguments(Compiler $compiler, $isArray = false) { - $compiler->raw('('); + $compiler->raw($isArray ? '[' : '('); $first = true; @@ -96,7 +106,7 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression } } - $compiler->raw(')'); + $compiler->raw($isArray ? ']' : ')'); } protected function getArguments($callable, $arguments) @@ -104,14 +114,14 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression $callType = $this->getAttribute('type'); $callName = $this->getAttribute('name'); - $parameters = array(); + $parameters = []; $named = false; foreach ($arguments as $name => $node) { - if (!is_int($name)) { + if (!\is_int($name)) { $named = true; $name = $this->normalizeName($name); } elseif ($named) { - throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName)); + throw new SyntaxError(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); } $parameters[$name] = $node; @@ -129,42 +139,42 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression $message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName); } - throw new LogicException($message); + throw new \LogicException($message); } $callableParameters = $this->getCallableParameters($callable, $isVariadic); - $arguments = array(); - $names = array(); - $missingArguments = array(); - $optionalArguments = array(); + $arguments = []; + $names = []; + $missingArguments = []; + $optionalArguments = []; $pos = 0; foreach ($callableParameters as $callableParameter) { $names[] = $name = $this->normalizeName($callableParameter->name); - if (array_key_exists($name, $parameters)) { - if (array_key_exists($pos, $parameters)) { - throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName)); + if (\array_key_exists($name, $parameters)) { + if (\array_key_exists($pos, $parameters)) { + throw new SyntaxError(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); } - if (count($missingArguments)) { - throw new Twig_Error_Syntax(sprintf( + if (\count($missingArguments)) { + throw new SyntaxError(sprintf( '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".', - $name, $callType, $callName, implode(', ', $names), count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments)) - ); + $name, $callType, $callName, implode(', ', $names), \count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments) + ), $this->getTemplateLine(), $this->getSourceContext()); } $arguments = array_merge($arguments, $optionalArguments); $arguments[] = $parameters[$name]; unset($parameters[$name]); - $optionalArguments = array(); - } elseif (array_key_exists($pos, $parameters)) { + $optionalArguments = []; + } elseif (\array_key_exists($pos, $parameters)) { $arguments = array_merge($arguments, $optionalArguments); $arguments[] = $parameters[$pos]; unset($parameters[$pos]); - $optionalArguments = array(); + $optionalArguments = []; ++$pos; } elseif ($callableParameter->isDefaultValueAvailable()) { - $optionalArguments[] = new Twig_Node_Expression_Constant($callableParameter->getDefaultValue(), -1); + $optionalArguments[] = new ConstantExpression($callableParameter->getDefaultValue(), -1); } elseif ($callableParameter->isOptional()) { if (empty($parameters)) { break; @@ -172,17 +182,17 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression $missingArguments[] = $name; } } else { - throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName)); + throw new SyntaxError(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); } } if ($isVariadic) { - $arbitraryArguments = new Twig_Node_Expression_Array(array(), -1); + $arbitraryArguments = new ArrayExpression([], -1); foreach ($parameters as $key => $value) { - if (is_int($key)) { + if (\is_int($key)) { $arbitraryArguments->addElement($value); } else { - $arbitraryArguments->addElement($value, new Twig_Node_Expression_Constant($key, -1)); + $arbitraryArguments->addElement($value, new ConstantExpression($key, -1)); } unset($parameters[$key]); } @@ -196,16 +206,20 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression if (!empty($parameters)) { $unknownParameter = null; foreach ($parameters as $parameter) { - if ($parameter instanceof Twig_Node) { + if ($parameter instanceof Node) { $unknownParameter = $parameter; break; } } - throw new Twig_Error_Syntax(sprintf( - 'Unknown argument%s "%s" for %s "%s(%s)".', - count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names) - ), $unknownParameter ? $unknownParameter->getTemplateLine() : -1); + throw new SyntaxError( + sprintf( + 'Unknown argument%s "%s" for %s "%s(%s)".', + \count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names) + ), + $unknownParameter ? $unknownParameter->getTemplateLine() : $this->getTemplateLine(), + $unknownParameter ? $unknownParameter->getSourceContext() : $this->getSourceContext() + ); } return $arguments; @@ -213,14 +227,14 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression protected function normalizeName($name) { - return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), $name)); + return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], ['\\1_\\2', '\\1_\\2'], $name)); } private function getCallableParameters($callable, $isVariadic) { list($r) = $this->reflectCallable($callable); if (null === $r) { - return array(); + return []; } $parameters = $r->getParameters(); @@ -240,15 +254,15 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression } if ($isVariadic) { $argument = end($parameters); - if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && array() === $argument->getDefaultValue()) { + if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && [] === $argument->getDefaultValue()) { array_pop($parameters); } else { $callableName = $r->name; - if ($r instanceof ReflectionMethod) { + if ($r instanceof \ReflectionMethod) { $callableName = $r->getDeclaringClass()->name.'::'.$callableName; } - throw new LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = array()".', $callableName, $this->getAttribute('type'), $this->getAttribute('name'))); + 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'))); } } @@ -261,31 +275,31 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression return $this->reflector; } - if (is_array($callable)) { + if (\is_array($callable)) { if (!method_exists($callable[0], $callable[1])) { // __call() - return array(null, array()); + return [null, []]; } - $r = new ReflectionMethod($callable[0], $callable[1]); - } elseif (is_object($callable) && !$callable instanceof Closure) { - $r = new ReflectionObject($callable); + $r = new \ReflectionMethod($callable[0], $callable[1]); + } elseif (\is_object($callable) && !$callable instanceof \Closure) { + $r = new \ReflectionObject($callable); $r = $r->getMethod('__invoke'); - $callable = array($callable, '__invoke'); - } elseif (is_string($callable) && false !== $pos = strpos($callable, '::')) { + $callable = [$callable, '__invoke']; + } elseif (\is_string($callable) && false !== $pos = strpos($callable, '::')) { $class = substr($callable, 0, $pos); $method = substr($callable, $pos + 2); if (!method_exists($class, $method)) { // __staticCall() - return array(null, array()); + return [null, []]; } - $r = new ReflectionMethod($callable); - $callable = array($class, $method); + $r = new \ReflectionMethod($callable); + $callable = [$class, $method]; } else { - $r = new ReflectionFunction($callable); + $r = new \ReflectionFunction($callable); } - return $this->reflector = array($r, $callable); + return $this->reflector = [$r, $callable]; } } -class_alias('Twig_Node_Expression_Call', 'Twig\Node\Expression\CallExpression', false); +class_alias('Twig\Node\Expression\CallExpression', 'Twig_Node_Expression_Call'); diff --git a/system/libs/Twig/Node/Expression/Conditional.php b/system/libs/Twig/Node/Expression/ConditionalExpression.php old mode 100755 new mode 100644 similarity index 52% rename from system/libs/Twig/Node/Expression/Conditional.php rename to system/libs/Twig/Node/Expression/ConditionalExpression.php index c339d773..b611218d --- a/system/libs/Twig/Node/Expression/Conditional.php +++ b/system/libs/Twig/Node/Expression/ConditionalExpression.php @@ -9,14 +9,19 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Conditional extends Twig_Node_Expression + +namespace Twig\Node\Expression; + +use Twig\Compiler; + +class ConditionalExpression extends AbstractExpression { - public function __construct(Twig_Node_Expression $expr1, Twig_Node_Expression $expr2, Twig_Node_Expression $expr3, $lineno) + public function __construct(AbstractExpression $expr1, AbstractExpression $expr2, AbstractExpression $expr3, $lineno) { - parent::__construct(array('expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3), array(), $lineno); + parent::__construct(['expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3], [], $lineno); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->raw('((') @@ -30,4 +35,4 @@ class Twig_Node_Expression_Conditional extends Twig_Node_Expression } } -class_alias('Twig_Node_Expression_Conditional', 'Twig\Node\Expression\ConditionalExpression', false); +class_alias('Twig\Node\Expression\ConditionalExpression', 'Twig_Node_Expression_Conditional'); diff --git a/system/libs/Twig/Node/Expression/Constant.php b/system/libs/Twig/Node/Expression/ConstantExpression.php old mode 100755 new mode 100644 similarity index 53% rename from system/libs/Twig/Node/Expression/Constant.php rename to system/libs/Twig/Node/Expression/ConstantExpression.php index bf4d031c..fd58264d --- a/system/libs/Twig/Node/Expression/Constant.php +++ b/system/libs/Twig/Node/Expression/ConstantExpression.php @@ -9,17 +9,22 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Constant extends Twig_Node_Expression + +namespace Twig\Node\Expression; + +use Twig\Compiler; + +class ConstantExpression extends AbstractExpression { public function __construct($value, $lineno) { - parent::__construct(array(), array('value' => $value), $lineno); + parent::__construct([], ['value' => $value], $lineno); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler->repr($this->getAttribute('value')); } } -class_alias('Twig_Node_Expression_Constant', 'Twig\Node\Expression\ConstantExpression', false); +class_alias('Twig\Node\Expression\ConstantExpression', 'Twig_Node_Expression_Constant'); diff --git a/system/libs/Twig/Node/Expression/Filter/Default.php b/system/libs/Twig/Node/Expression/Filter/Default.php deleted file mode 100755 index d2e19d54..00000000 --- a/system/libs/Twig/Node/Expression/Filter/Default.php +++ /dev/null @@ -1,45 +0,0 @@ - - * {{ var.foo|default('foo item on var is not defined') }} - * - * - * @author Fabien Potencier - */ -class Twig_Node_Expression_Filter_Default extends Twig_Node_Expression_Filter -{ - public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null) - { - $default = new Twig_Node_Expression_Filter($node, new Twig_Node_Expression_Constant('default', $node->getTemplateLine()), $arguments, $node->getTemplateLine()); - - if ('default' === $filterName->getAttribute('value') && ($node instanceof Twig_Node_Expression_Name || $node instanceof Twig_Node_Expression_GetAttr)) { - $test = new Twig_Node_Expression_Test_Defined(clone $node, 'defined', new Twig_Node(), $node->getTemplateLine()); - $false = count($arguments) ? $arguments->getNode(0) : new Twig_Node_Expression_Constant('', $node->getTemplateLine()); - - $node = new Twig_Node_Expression_Conditional($test, $default, $false, $node->getTemplateLine()); - } else { - $node = $default; - } - - parent::__construct($node, $filterName, $arguments, $lineno, $tag); - } - - public function compile(Twig_Compiler $compiler) - { - $compiler->subcompile($this->getNode('node')); - } -} - -class_alias('Twig_Node_Expression_Filter_Default', 'Twig\Node\Expression\Filter\DefaultFilter', false); diff --git a/system/libs/Twig/Node/Expression/Filter/DefaultFilter.php b/system/libs/Twig/Node/Expression/Filter/DefaultFilter.php new file mode 100644 index 00000000..7c5e2d20 --- /dev/null +++ b/system/libs/Twig/Node/Expression/Filter/DefaultFilter.php @@ -0,0 +1,54 @@ + + */ +class DefaultFilter extends FilterExpression +{ + public function __construct(\Twig_NodeInterface $node, ConstantExpression $filterName, \Twig_NodeInterface $arguments, $lineno, $tag = null) + { + $default = new FilterExpression($node, new ConstantExpression('default', $node->getTemplateLine()), $arguments, $node->getTemplateLine()); + + if ('default' === $filterName->getAttribute('value') && ($node instanceof NameExpression || $node instanceof GetAttrExpression)) { + $test = new DefinedTest(clone $node, 'defined', new Node(), $node->getTemplateLine()); + $false = \count($arguments) ? $arguments->getNode(0) : new ConstantExpression('', $node->getTemplateLine()); + + $node = new ConditionalExpression($test, $default, $false, $node->getTemplateLine()); + } else { + $node = $default; + } + + parent::__construct($node, $filterName, $arguments, $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler->subcompile($this->getNode('node')); + } +} + +class_alias('Twig\Node\Expression\Filter\DefaultFilter', 'Twig_Node_Expression_Filter_Default'); diff --git a/system/libs/Twig/Node/Expression/Filter.php b/system/libs/Twig/Node/Expression/FilterExpression.php old mode 100755 new mode 100644 similarity index 58% rename from system/libs/Twig/Node/Expression/Filter.php rename to system/libs/Twig/Node/Expression/FilterExpression.php index 12da1d67..6131c2fd --- a/system/libs/Twig/Node/Expression/Filter.php +++ b/system/libs/Twig/Node/Expression/FilterExpression.php @@ -9,14 +9,20 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call + +namespace Twig\Node\Expression; + +use Twig\Compiler; +use Twig\TwigFilter; + +class FilterExpression extends CallExpression { - public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null) + public function __construct(\Twig_NodeInterface $node, ConstantExpression $filterName, \Twig_NodeInterface $arguments, $lineno, $tag = null) { - parent::__construct(array('node' => $node, 'filter' => $filterName, 'arguments' => $arguments), array(), $lineno, $tag); + parent::__construct(['node' => $node, 'filter' => $filterName, 'arguments' => $arguments], [], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $name = $this->getNode('filter')->getAttribute('value'); $filter = $compiler->getEnvironment()->getFilter($name); @@ -27,10 +33,10 @@ class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call $this->setAttribute('needs_environment', $filter->needsEnvironment()); $this->setAttribute('needs_context', $filter->needsContext()); $this->setAttribute('arguments', $filter->getArguments()); - if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof Twig_SimpleFilter) { + if ($filter instanceof \Twig_FilterCallableInterface || $filter instanceof TwigFilter) { $this->setAttribute('callable', $filter->getCallable()); } - if ($filter instanceof Twig_SimpleFilter) { + if ($filter instanceof TwigFilter) { $this->setAttribute('is_variadic', $filter->isVariadic()); } @@ -38,4 +44,4 @@ class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call } } -class_alias('Twig_Node_Expression_Filter', 'Twig\Node\Expression\FilterExpression', false); +class_alias('Twig\Node\Expression\FilterExpression', 'Twig_Node_Expression_Filter'); diff --git a/system/libs/Twig/Node/Expression/Function.php b/system/libs/Twig/Node/Expression/FunctionExpression.php old mode 100755 new mode 100644 similarity index 64% rename from system/libs/Twig/Node/Expression/Function.php rename to system/libs/Twig/Node/Expression/FunctionExpression.php index cdee7c97..cf2c72b6 --- a/system/libs/Twig/Node/Expression/Function.php +++ b/system/libs/Twig/Node/Expression/FunctionExpression.php @@ -8,14 +8,20 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Function extends Twig_Node_Expression_Call + +namespace Twig\Node\Expression; + +use Twig\Compiler; +use Twig\TwigFunction; + +class FunctionExpression extends CallExpression { - public function __construct($name, Twig_NodeInterface $arguments, $lineno) + public function __construct($name, \Twig_NodeInterface $arguments, $lineno) { - parent::__construct(array('arguments' => $arguments), array('name' => $name, 'is_defined_test' => false), $lineno); + parent::__construct(['arguments' => $arguments], ['name' => $name, 'is_defined_test' => false], $lineno); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $name = $this->getAttribute('name'); $function = $compiler->getEnvironment()->getFunction($name); @@ -26,7 +32,7 @@ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call $this->setAttribute('needs_environment', $function->needsEnvironment()); $this->setAttribute('needs_context', $function->needsContext()); $this->setAttribute('arguments', $function->getArguments()); - if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) { + if ($function instanceof \Twig_FunctionCallableInterface || $function instanceof TwigFunction) { $callable = $function->getCallable(); if ('constant' === $name && $this->getAttribute('is_defined_test')) { $callable = 'twig_constant_is_defined'; @@ -34,7 +40,7 @@ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call $this->setAttribute('callable', $callable); } - if ($function instanceof Twig_SimpleFunction) { + if ($function instanceof TwigFunction) { $this->setAttribute('is_variadic', $function->isVariadic()); } @@ -42,4 +48,4 @@ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call } } -class_alias('Twig_Node_Expression_Function', 'Twig\Node\Expression\FunctionExpression', false); +class_alias('Twig\Node\Expression\FunctionExpression', 'Twig_Node_Expression_Function'); diff --git a/system/libs/Twig/Node/Expression/GetAttr.php b/system/libs/Twig/Node/Expression/GetAttrExpression.php old mode 100755 new mode 100644 similarity index 68% rename from system/libs/Twig/Node/Expression/GetAttr.php rename to system/libs/Twig/Node/Expression/GetAttrExpression.php index b7823acc..b790bf7a --- a/system/libs/Twig/Node/Expression/GetAttr.php +++ b/system/libs/Twig/Node/Expression/GetAttrExpression.php @@ -9,25 +9,31 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_GetAttr extends Twig_Node_Expression + +namespace Twig\Node\Expression; + +use Twig\Compiler; +use Twig\Template; + +class GetAttrExpression extends AbstractExpression { - public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression $arguments = null, $type, $lineno) + public function __construct(AbstractExpression $node, AbstractExpression $attribute, AbstractExpression $arguments = null, $type, $lineno) { - $nodes = array('node' => $node, 'attribute' => $attribute); + $nodes = ['node' => $node, 'attribute' => $attribute]; if (null !== $arguments) { $nodes['arguments'] = $arguments; } - parent::__construct($nodes, array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false), $lineno); + parent::__construct($nodes, ['type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false], $lineno); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { if ($this->getAttribute('disable_c_ext')) { @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); } - if (function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) { + if (\function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) { $compiler->raw('twig_template_get_attributes($this, '); } else { $compiler->raw('$this->getAttribute('); @@ -44,14 +50,14 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression // only generate optional arguments when needed (to make generated code more readable) $needFourth = $this->getAttribute('ignore_strict_check'); $needThird = $needFourth || $this->getAttribute('is_defined_test'); - $needSecond = $needThird || Twig_Template::ANY_CALL !== $this->getAttribute('type'); + $needSecond = $needThird || Template::ANY_CALL !== $this->getAttribute('type'); $needFirst = $needSecond || $this->hasNode('arguments'); if ($needFirst) { if ($this->hasNode('arguments')) { $compiler->raw(', ')->subcompile($this->getNode('arguments')); } else { - $compiler->raw(', array()'); + $compiler->raw(', []'); } } @@ -71,4 +77,4 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression } } -class_alias('Twig_Node_Expression_GetAttr', 'Twig\Node\Expression\GetAttrExpression', false); +class_alias('Twig\Node\Expression\GetAttrExpression', 'Twig_Node_Expression_GetAttr'); diff --git a/system/libs/Twig/Node/Expression/InlinePrint.php b/system/libs/Twig/Node/Expression/InlinePrint.php new file mode 100644 index 00000000..469e7367 --- /dev/null +++ b/system/libs/Twig/Node/Expression/InlinePrint.php @@ -0,0 +1,35 @@ + $node], [], $lineno); + } + + public function compile(Compiler $compiler) + { + $compiler + ->raw('print (') + ->subcompile($this->getNode('node')) + ->raw(')') + ; + } +} diff --git a/system/libs/Twig/Node/Expression/MethodCall.php b/system/libs/Twig/Node/Expression/MethodCallExpression.php old mode 100755 new mode 100644 similarity index 59% rename from system/libs/Twig/Node/Expression/MethodCall.php rename to system/libs/Twig/Node/Expression/MethodCallExpression.php index 709016eb..f6311249 --- a/system/libs/Twig/Node/Expression/MethodCall.php +++ b/system/libs/Twig/Node/Expression/MethodCallExpression.php @@ -8,18 +8,23 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_MethodCall extends Twig_Node_Expression -{ - public function __construct(Twig_Node_Expression $node, $method, Twig_Node_Expression_Array $arguments, $lineno) - { - parent::__construct(array('node' => $node, 'arguments' => $arguments), array('method' => $method, 'safe' => false), $lineno); - if ($node instanceof Twig_Node_Expression_Name) { +namespace Twig\Node\Expression; + +use Twig\Compiler; + +class MethodCallExpression extends AbstractExpression +{ + public function __construct(AbstractExpression $node, $method, ArrayExpression $arguments, $lineno) + { + parent::__construct(['node' => $node, 'arguments' => $arguments], ['method' => $method, 'safe' => false], $lineno); + + if ($node instanceof NameExpression) { $node->setAttribute('always_defined', true); } } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->subcompile($this->getNode('node')) @@ -40,4 +45,4 @@ class Twig_Node_Expression_MethodCall extends Twig_Node_Expression } } -class_alias('Twig_Node_Expression_MethodCall', 'Twig\Node\Expression\MethodCallExpression', false); +class_alias('Twig\Node\Expression\MethodCallExpression', 'Twig_Node_Expression_MethodCall'); diff --git a/system/libs/Twig/Node/Expression/Name.php b/system/libs/Twig/Node/Expression/NameExpression.php old mode 100755 new mode 100644 similarity index 73% rename from system/libs/Twig/Node/Expression/Name.php rename to system/libs/Twig/Node/Expression/NameExpression.php index 9d5a21f8..d3f7d107 --- a/system/libs/Twig/Node/Expression/Name.php +++ b/system/libs/Twig/Node/Expression/NameExpression.php @@ -9,20 +9,25 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Name extends Twig_Node_Expression + +namespace Twig\Node\Expression; + +use Twig\Compiler; + +class NameExpression extends AbstractExpression { - protected $specialVars = array( + protected $specialVars = [ '_self' => '$this', '_context' => '$context', '_charset' => '$this->env->getCharset()', - ); + ]; public function __construct($name, $lineno) { - parent::__construct(array(), array('name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false), $lineno); + parent::__construct([], ['name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false], $lineno); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $name = $this->getAttribute('name'); @@ -31,8 +36,20 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression if ($this->getAttribute('is_defined_test')) { if ($this->isSpecial()) { $compiler->repr(true); + } elseif (\PHP_VERSION_ID >= 700400) { + $compiler + ->raw('array_key_exists(') + ->string($name) + ->raw(', $context)') + ; } else { - $compiler->raw('array_key_exists(')->repr($name)->raw(', $context)'); + $compiler + ->raw('(isset($context[') + ->string($name) + ->raw(']) || array_key_exists(') + ->string($name) + ->raw(', $context))') + ; } } elseif ($this->isSpecial()) { $compiler->raw($this->specialVars[$name]); @@ -43,7 +60,7 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression ->raw(']') ; } else { - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { // use PHP 7 null coalescing operator $compiler ->raw('($context[') @@ -56,7 +73,7 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression } else { $compiler->raw('$this->getContext($context, ')->string($name)->raw('))'); } - } elseif (PHP_VERSION_ID >= 50400) { + } elseif (\PHP_VERSION_ID >= 50400) { // PHP 5.4 ternary operator performance was optimized $compiler ->raw('(isset($context[') @@ -99,4 +116,4 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression } } -class_alias('Twig_Node_Expression_Name', 'Twig\Node\Expression\NameExpression', false); +class_alias('Twig\Node\Expression\NameExpression', 'Twig_Node_Expression_Name'); diff --git a/system/libs/Twig/Node/Expression/NullCoalesce.php b/system/libs/Twig/Node/Expression/NullCoalesce.php deleted file mode 100644 index eaafa4c9..00000000 --- a/system/libs/Twig/Node/Expression/NullCoalesce.php +++ /dev/null @@ -1,48 +0,0 @@ -getTemplateLine()), - new Twig_Node_Expression_Unary_Not(new Twig_Node_Expression_Test_Null($left, 'null', new Twig_Node(), $left->getTemplateLine()), $left->getTemplateLine()), - $left->getTemplateLine() - ); - - parent::__construct($test, $left, $right, $lineno); - } - - public function compile(Twig_Compiler $compiler) - { - /* - * This optimizes only one case. PHP 7 also supports more complex expressions - * that can return null. So, for instance, if log is defined, log("foo") ?? "..." works, - * but log($a["foo"]) ?? "..." does not if $a["foo"] is not defined. More advanced - * cases might be implemented as an optimizer node visitor, but has not been done - * as benefits are probably not worth the added complexity. - */ - if (PHP_VERSION_ID >= 70000 && $this->getNode('expr2') instanceof Twig_Node_Expression_Name) { - $this->getNode('expr2')->setAttribute('always_defined', true); - $compiler - ->raw('((') - ->subcompile($this->getNode('expr2')) - ->raw(') ?? (') - ->subcompile($this->getNode('expr3')) - ->raw('))') - ; - } else { - parent::compile($compiler); - } - } -} - -class_alias('Twig_Node_Expression_NullCoalesce', 'Twig\Node\Expression\NullCoalesceExpression', false); diff --git a/system/libs/Twig/Node/Expression/NullCoalesceExpression.php b/system/libs/Twig/Node/Expression/NullCoalesceExpression.php new file mode 100644 index 00000000..917d31a3 --- /dev/null +++ b/system/libs/Twig/Node/Expression/NullCoalesceExpression.php @@ -0,0 +1,62 @@ +getTemplateLine()); + // for "block()", we don't need the null test as the return value is always a string + if (!$left instanceof BlockReferenceExpression) { + $test = new AndBinary( + $test, + new NotUnary(new NullTest($left, 'null', new Node(), $left->getTemplateLine()), $left->getTemplateLine()), + $left->getTemplateLine() + ); + } + + parent::__construct($test, $left, $right, $lineno); + } + + public function compile(Compiler $compiler) + { + /* + * This optimizes only one case. PHP 7 also supports more complex expressions + * that can return null. So, for instance, if log is defined, log("foo") ?? "..." works, + * but log($a["foo"]) ?? "..." does not if $a["foo"] is not defined. More advanced + * cases might be implemented as an optimizer node visitor, but has not been done + * as benefits are probably not worth the added complexity. + */ + if (\PHP_VERSION_ID >= 70000 && $this->getNode('expr2') instanceof NameExpression) { + $this->getNode('expr2')->setAttribute('always_defined', true); + $compiler + ->raw('((') + ->subcompile($this->getNode('expr2')) + ->raw(') ?? (') + ->subcompile($this->getNode('expr3')) + ->raw('))') + ; + } else { + parent::compile($compiler); + } + } +} + +class_alias('Twig\Node\Expression\NullCoalesceExpression', 'Twig_Node_Expression_NullCoalesce'); diff --git a/system/libs/Twig/Node/Expression/Parent.php b/system/libs/Twig/Node/Expression/ParentExpression.php old mode 100755 new mode 100644 similarity index 73% rename from system/libs/Twig/Node/Expression/Parent.php rename to system/libs/Twig/Node/Expression/ParentExpression.php index 78692db2..12472830 --- a/system/libs/Twig/Node/Expression/Parent.php +++ b/system/libs/Twig/Node/Expression/ParentExpression.php @@ -10,19 +10,23 @@ * file that was distributed with this source code. */ +namespace Twig\Node\Expression; + +use Twig\Compiler; + /** * Represents a parent node. * * @author Fabien Potencier */ -class Twig_Node_Expression_Parent extends Twig_Node_Expression +class ParentExpression extends AbstractExpression { public function __construct($name, $lineno, $tag = null) { - parent::__construct(array(), array('output' => false, 'name' => $name), $lineno, $tag); + parent::__construct([], ['output' => false, 'name' => $name], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { if ($this->getAttribute('output')) { $compiler @@ -41,4 +45,4 @@ class Twig_Node_Expression_Parent extends Twig_Node_Expression } } -class_alias('Twig_Node_Expression_Parent', 'Twig\Node\Expression\ParentExpression', false); +class_alias('Twig\Node\Expression\ParentExpression', 'Twig_Node_Expression_Parent'); diff --git a/system/libs/Twig/Node/Expression/TempName.php b/system/libs/Twig/Node/Expression/TempNameExpression.php old mode 100755 new mode 100644 similarity index 57% rename from system/libs/Twig/Node/Expression/TempName.php rename to system/libs/Twig/Node/Expression/TempNameExpression.php index 0a86e003..ce0a1589 --- a/system/libs/Twig/Node/Expression/TempName.php +++ b/system/libs/Twig/Node/Expression/TempNameExpression.php @@ -8,14 +8,19 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_TempName extends Twig_Node_Expression + +namespace Twig\Node\Expression; + +use Twig\Compiler; + +class TempNameExpression extends AbstractExpression { public function __construct($name, $lineno) { - parent::__construct(array(), array('name' => $name), $lineno); + parent::__construct([], ['name' => $name], $lineno); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->raw('$_') @@ -25,4 +30,4 @@ class Twig_Node_Expression_TempName extends Twig_Node_Expression } } -class_alias('Twig_Node_Expression_TempName', 'Twig\Node\Expression\TempNameExpression', false); +class_alias('Twig\Node\Expression\TempNameExpression', 'Twig_Node_Expression_TempName'); diff --git a/system/libs/Twig/Node/Expression/Test/Constant.php b/system/libs/Twig/Node/Expression/Test/ConstantTest.php old mode 100755 new mode 100644 similarity index 66% rename from system/libs/Twig/Node/Expression/Test/Constant.php rename to system/libs/Twig/Node/Expression/Test/ConstantTest.php index a51a4ba1..78353a8b --- a/system/libs/Twig/Node/Expression/Test/Constant.php +++ b/system/libs/Twig/Node/Expression/Test/ConstantTest.php @@ -9,20 +9,23 @@ * file that was distributed with this source code. */ +namespace Twig\Node\Expression\Test; + +use Twig\Compiler; +use Twig\Node\Expression\TestExpression; + /** * Checks if a variable is the exact same value as a constant. * - *
- *  {% if post.status is constant('Post::PUBLISHED') %}
- *    the status attribute is exactly the same as Post::PUBLISHED
- *  {% endif %}
- * 
+ * {% if post.status is constant('Post::PUBLISHED') %} + * the status attribute is exactly the same as Post::PUBLISHED + * {% endif %} * * @author Fabien Potencier */ -class Twig_Node_Expression_Test_Constant extends Twig_Node_Expression_Test +class ConstantTest extends TestExpression { - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->raw('(') @@ -45,4 +48,4 @@ class Twig_Node_Expression_Test_Constant extends Twig_Node_Expression_Test } } -class_alias('Twig_Node_Expression_Test_Constant', 'Twig\Node\Expression\Test\ConstantTest', false); +class_alias('Twig\Node\Expression\Test\ConstantTest', 'Twig_Node_Expression_Test_Constant'); diff --git a/system/libs/Twig/Node/Expression/Test/Defined.php b/system/libs/Twig/Node/Expression/Test/Defined.php deleted file mode 100755 index 2136c390..00000000 --- a/system/libs/Twig/Node/Expression/Test/Defined.php +++ /dev/null @@ -1,61 +0,0 @@ - - * {# defined works with variable names and variable attributes #} - * {% if foo is defined %} - * {# ... #} - * {% endif %} - * - * - * @author Fabien Potencier - */ -class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test -{ - public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno) - { - if ($node instanceof Twig_Node_Expression_Name) { - $node->setAttribute('is_defined_test', true); - } elseif ($node instanceof Twig_Node_Expression_GetAttr) { - $node->setAttribute('is_defined_test', true); - $this->changeIgnoreStrictCheck($node); - } elseif ($node instanceof Twig_Node_Expression_BlockReference) { - $node->setAttribute('is_defined_test', true); - } elseif ($node instanceof Twig_Node_Expression_Function && 'constant' === $node->getAttribute('name')) { - $node->setAttribute('is_defined_test', true); - } elseif ($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array) { - $node = new Twig_Node_Expression_Constant(true, $node->getTemplateLine()); - } else { - throw new Twig_Error_Syntax('The "defined" test only works with simple variables.', $this->getTemplateLine()); - } - - parent::__construct($node, $name, $arguments, $lineno); - } - - protected function changeIgnoreStrictCheck(Twig_Node_Expression_GetAttr $node) - { - $node->setAttribute('ignore_strict_check', true); - - if ($node->getNode('node') instanceof Twig_Node_Expression_GetAttr) { - $this->changeIgnoreStrictCheck($node->getNode('node')); - } - } - - public function compile(Twig_Compiler $compiler) - { - $compiler->subcompile($this->getNode('node')); - } -} - -class_alias('Twig_Node_Expression_Test_Defined', 'Twig\Node\Expression\Test\DefinedTest', false); diff --git a/system/libs/Twig/Node/Expression/Test/DefinedTest.php b/system/libs/Twig/Node/Expression/Test/DefinedTest.php new file mode 100644 index 00000000..2222e11c --- /dev/null +++ b/system/libs/Twig/Node/Expression/Test/DefinedTest.php @@ -0,0 +1,71 @@ + + */ +class DefinedTest extends TestExpression +{ + public function __construct(\Twig_NodeInterface $node, $name, \Twig_NodeInterface $arguments = null, $lineno) + { + if ($node instanceof NameExpression) { + $node->setAttribute('is_defined_test', true); + } elseif ($node instanceof GetAttrExpression) { + $node->setAttribute('is_defined_test', true); + $this->changeIgnoreStrictCheck($node); + } elseif ($node instanceof BlockReferenceExpression) { + $node->setAttribute('is_defined_test', true); + } elseif ($node instanceof FunctionExpression && 'constant' === $node->getAttribute('name')) { + $node->setAttribute('is_defined_test', true); + } elseif ($node instanceof ConstantExpression || $node instanceof ArrayExpression) { + $node = new ConstantExpression(true, $node->getTemplateLine()); + } else { + throw new SyntaxError('The "defined" test only works with simple variables.', $lineno); + } + + parent::__construct($node, $name, $arguments, $lineno); + } + + protected function changeIgnoreStrictCheck(GetAttrExpression $node) + { + $node->setAttribute('ignore_strict_check', true); + + if ($node->getNode('node') instanceof GetAttrExpression) { + $this->changeIgnoreStrictCheck($node->getNode('node')); + } + } + + public function compile(Compiler $compiler) + { + $compiler->subcompile($this->getNode('node')); + } +} + +class_alias('Twig\Node\Expression\Test\DefinedTest', 'Twig_Node_Expression_Test_Defined'); diff --git a/system/libs/Twig/Node/Expression/Test/Divisibleby.php b/system/libs/Twig/Node/Expression/Test/DivisiblebyTest.php old mode 100755 new mode 100644 similarity index 67% rename from system/libs/Twig/Node/Expression/Test/Divisibleby.php rename to system/libs/Twig/Node/Expression/Test/DivisiblebyTest.php index a5d71961..05c8ad8f --- a/system/libs/Twig/Node/Expression/Test/Divisibleby.php +++ b/system/libs/Twig/Node/Expression/Test/DivisiblebyTest.php @@ -9,18 +9,21 @@ * file that was distributed with this source code. */ +namespace Twig\Node\Expression\Test; + +use Twig\Compiler; +use Twig\Node\Expression\TestExpression; + /** * Checks if a variable is divisible by a number. * - *
  *  {% if loop.index is divisible by(3) %}
- * 
* * @author Fabien Potencier */ -class Twig_Node_Expression_Test_Divisibleby extends Twig_Node_Expression_Test +class DivisiblebyTest extends TestExpression { - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->raw('(0 == ') @@ -32,4 +35,4 @@ class Twig_Node_Expression_Test_Divisibleby extends Twig_Node_Expression_Test } } -class_alias('Twig_Node_Expression_Test_Divisibleby', 'Twig\Node\Expression\Test\DivisiblebyTest', false); +class_alias('Twig\Node\Expression\Test\DivisiblebyTest', 'Twig_Node_Expression_Test_Divisibleby'); diff --git a/system/libs/Twig/Node/Expression/Test/Even.php b/system/libs/Twig/Node/Expression/Test/EvenTest.php old mode 100755 new mode 100644 similarity index 64% rename from system/libs/Twig/Node/Expression/Test/Even.php rename to system/libs/Twig/Node/Expression/Test/EvenTest.php index 7e198bea..3b955d26 --- a/system/libs/Twig/Node/Expression/Test/Even.php +++ b/system/libs/Twig/Node/Expression/Test/EvenTest.php @@ -9,18 +9,21 @@ * file that was distributed with this source code. */ +namespace Twig\Node\Expression\Test; + +use Twig\Compiler; +use Twig\Node\Expression\TestExpression; + /** * Checks if a number is even. * - *
  *  {{ var is even }}
- * 
* * @author Fabien Potencier */ -class Twig_Node_Expression_Test_Even extends Twig_Node_Expression_Test +class EvenTest extends TestExpression { - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->raw('(') @@ -31,4 +34,4 @@ class Twig_Node_Expression_Test_Even extends Twig_Node_Expression_Test } } -class_alias('Twig_Node_Expression_Test_Even', 'Twig\Node\Expression\Test\EvenTest', false); +class_alias('Twig\Node\Expression\Test\EvenTest', 'Twig_Node_Expression_Test_Even'); diff --git a/system/libs/Twig/Node/Expression/Test/Null.php b/system/libs/Twig/Node/Expression/Test/NullTest.php old mode 100755 new mode 100644 similarity index 63% rename from system/libs/Twig/Node/Expression/Test/Null.php rename to system/libs/Twig/Node/Expression/Test/NullTest.php index 3746e4cb..24d39978 --- a/system/libs/Twig/Node/Expression/Test/Null.php +++ b/system/libs/Twig/Node/Expression/Test/NullTest.php @@ -9,18 +9,21 @@ * file that was distributed with this source code. */ +namespace Twig\Node\Expression\Test; + +use Twig\Compiler; +use Twig\Node\Expression\TestExpression; + /** * Checks that a variable is null. * - *
  *  {{ var is none }}
- * 
* * @author Fabien Potencier */ -class Twig_Node_Expression_Test_Null extends Twig_Node_Expression_Test +class NullTest extends TestExpression { - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->raw('(null === ') @@ -30,4 +33,4 @@ class Twig_Node_Expression_Test_Null extends Twig_Node_Expression_Test } } -class_alias('Twig_Node_Expression_Test_Null', 'Twig\Node\Expression\Test\NullTest', false); +class_alias('Twig\Node\Expression\Test\NullTest', 'Twig_Node_Expression_Test_Null'); diff --git a/system/libs/Twig/Node/Expression/Test/Odd.php b/system/libs/Twig/Node/Expression/Test/OddTest.php old mode 100755 new mode 100644 similarity index 64% rename from system/libs/Twig/Node/Expression/Test/Odd.php rename to system/libs/Twig/Node/Expression/Test/OddTest.php index 0c6c099b..2dc693a9 --- a/system/libs/Twig/Node/Expression/Test/Odd.php +++ b/system/libs/Twig/Node/Expression/Test/OddTest.php @@ -9,18 +9,21 @@ * file that was distributed with this source code. */ +namespace Twig\Node\Expression\Test; + +use Twig\Compiler; +use Twig\Node\Expression\TestExpression; + /** * Checks if a number is odd. * - *
  *  {{ var is odd }}
- * 
* * @author Fabien Potencier */ -class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test +class OddTest extends TestExpression { - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->raw('(') @@ -31,4 +34,4 @@ class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test } } -class_alias('Twig_Node_Expression_Test_Odd', 'Twig\Node\Expression\Test\OddTest', false); +class_alias('Twig\Node\Expression\Test\OddTest', 'Twig_Node_Expression_Test_Odd'); diff --git a/system/libs/Twig/Node/Expression/Test/Sameas.php b/system/libs/Twig/Node/Expression/Test/SameasTest.php old mode 100755 new mode 100644 similarity index 66% rename from system/libs/Twig/Node/Expression/Test/Sameas.php rename to system/libs/Twig/Node/Expression/Test/SameasTest.php index e95ff1f2..75f2b82a --- a/system/libs/Twig/Node/Expression/Test/Sameas.php +++ b/system/libs/Twig/Node/Expression/Test/SameasTest.php @@ -9,14 +9,19 @@ * file that was distributed with this source code. */ +namespace Twig\Node\Expression\Test; + +use Twig\Compiler; +use Twig\Node\Expression\TestExpression; + /** * Checks if a variable is the same as another one (=== in PHP). * * @author Fabien Potencier */ -class Twig_Node_Expression_Test_Sameas extends Twig_Node_Expression_Test +class SameasTest extends TestExpression { - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->raw('(') @@ -28,4 +33,4 @@ class Twig_Node_Expression_Test_Sameas extends Twig_Node_Expression_Test } } -class_alias('Twig_Node_Expression_Test_Sameas', 'Twig\Node\Expression\Test\SameasTest', false); +class_alias('Twig\Node\Expression\Test\SameasTest', 'Twig_Node_Expression_Test_Sameas'); diff --git a/system/libs/Twig/Node/Expression/Test.php b/system/libs/Twig/Node/Expression/TestExpression.php old mode 100755 new mode 100644 similarity index 51% rename from system/libs/Twig/Node/Expression/Test.php rename to system/libs/Twig/Node/Expression/TestExpression.php index ad102ba6..8fc31d3a --- a/system/libs/Twig/Node/Expression/Test.php +++ b/system/libs/Twig/Node/Expression/TestExpression.php @@ -8,19 +8,25 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Test extends Twig_Node_Expression_Call + +namespace Twig\Node\Expression; + +use Twig\Compiler; +use Twig\TwigTest; + +class TestExpression extends CallExpression { - public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno) + public function __construct(\Twig_NodeInterface $node, $name, \Twig_NodeInterface $arguments = null, $lineno) { - $nodes = array('node' => $node); + $nodes = ['node' => $node]; if (null !== $arguments) { $nodes['arguments'] = $arguments; } - parent::__construct($nodes, array('name' => $name), $lineno); + parent::__construct($nodes, ['name' => $name], $lineno); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $name = $this->getAttribute('name'); $test = $compiler->getEnvironment()->getTest($name); @@ -28,10 +34,13 @@ class Twig_Node_Expression_Test extends Twig_Node_Expression_Call $this->setAttribute('name', $name); $this->setAttribute('type', 'test'); $this->setAttribute('thing', $test); - if ($test instanceof Twig_TestCallableInterface || $test instanceof Twig_SimpleTest) { + if ($test instanceof TwigTest) { + $this->setAttribute('arguments', $test->getArguments()); + } + if ($test instanceof \Twig_TestCallableInterface || $test instanceof TwigTest) { $this->setAttribute('callable', $test->getCallable()); } - if ($test instanceof Twig_SimpleTest) { + if ($test instanceof TwigTest) { $this->setAttribute('is_variadic', $test->isVariadic()); } @@ -39,4 +48,4 @@ class Twig_Node_Expression_Test extends Twig_Node_Expression_Call } } -class_alias('Twig_Node_Expression_Test', 'Twig\Node\Expression\TestExpression', false); +class_alias('Twig\Node\Expression\TestExpression', 'Twig_Node_Expression_Test'); diff --git a/system/libs/Twig/Node/Expression/Unary.php b/system/libs/Twig/Node/Expression/Unary.php deleted file mode 100755 index 5804485e..00000000 --- a/system/libs/Twig/Node/Expression/Unary.php +++ /dev/null @@ -1,29 +0,0 @@ - $node), array(), $lineno); - } - - public function compile(Twig_Compiler $compiler) - { - $compiler->raw(' '); - $this->operator($compiler); - $compiler->subcompile($this->getNode('node')); - } - - abstract public function operator(Twig_Compiler $compiler); -} - -class_alias('Twig_Node_Expression_Unary', 'Twig\Node\Expression\Unary\AbstractUnary', false); diff --git a/system/libs/Twig/Node/Expression/Unary/AbstractUnary.php b/system/libs/Twig/Node/Expression/Unary/AbstractUnary.php new file mode 100644 index 00000000..415c3d40 --- /dev/null +++ b/system/libs/Twig/Node/Expression/Unary/AbstractUnary.php @@ -0,0 +1,35 @@ + $node], [], $lineno); + } + + public function compile(Compiler $compiler) + { + $compiler->raw(' '); + $this->operator($compiler); + $compiler->subcompile($this->getNode('node')); + } + + abstract public function operator(Compiler $compiler); +} + +class_alias('Twig\Node\Expression\Unary\AbstractUnary', 'Twig_Node_Expression_Unary'); diff --git a/system/libs/Twig/Node/Expression/Unary/Neg.php b/system/libs/Twig/Node/Expression/Unary/NegUnary.php old mode 100755 new mode 100644 similarity index 53% rename from system/libs/Twig/Node/Expression/Unary/Neg.php rename to system/libs/Twig/Node/Expression/Unary/NegUnary.php index 039d933d..dfb6f542 --- a/system/libs/Twig/Node/Expression/Unary/Neg.php +++ b/system/libs/Twig/Node/Expression/Unary/NegUnary.php @@ -9,12 +9,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Unary_Neg extends Twig_Node_Expression_Unary + +namespace Twig\Node\Expression\Unary; + +use Twig\Compiler; + +class NegUnary extends AbstractUnary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { $compiler->raw('-'); } } -class_alias('Twig_Node_Expression_Unary_Neg', 'Twig\Node\Expression\Unary\NegUnary', false); +class_alias('Twig\Node\Expression\Unary\NegUnary', 'Twig_Node_Expression_Unary_Neg'); diff --git a/system/libs/Twig/Node/Expression/Unary/Not.php b/system/libs/Twig/Node/Expression/Unary/NotUnary.php old mode 100755 new mode 100644 similarity index 53% rename from system/libs/Twig/Node/Expression/Unary/Not.php rename to system/libs/Twig/Node/Expression/Unary/NotUnary.php index a0860b18..7bdde96f --- a/system/libs/Twig/Node/Expression/Unary/Not.php +++ b/system/libs/Twig/Node/Expression/Unary/NotUnary.php @@ -9,12 +9,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Unary_Not extends Twig_Node_Expression_Unary + +namespace Twig\Node\Expression\Unary; + +use Twig\Compiler; + +class NotUnary extends AbstractUnary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { $compiler->raw('!'); } } -class_alias('Twig_Node_Expression_Unary_Not', 'Twig\Node\Expression\Unary\NotUnary', false); +class_alias('Twig\Node\Expression\Unary\NotUnary', 'Twig_Node_Expression_Unary_Not'); diff --git a/system/libs/Twig/Node/Expression/Unary/Pos.php b/system/libs/Twig/Node/Expression/Unary/PosUnary.php old mode 100755 new mode 100644 similarity index 53% rename from system/libs/Twig/Node/Expression/Unary/Pos.php rename to system/libs/Twig/Node/Expression/Unary/PosUnary.php index eeff5452..52d5d0c8 --- a/system/libs/Twig/Node/Expression/Unary/Pos.php +++ b/system/libs/Twig/Node/Expression/Unary/PosUnary.php @@ -9,12 +9,17 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Node_Expression_Unary_Pos extends Twig_Node_Expression_Unary + +namespace Twig\Node\Expression\Unary; + +use Twig\Compiler; + +class PosUnary extends AbstractUnary { - public function operator(Twig_Compiler $compiler) + public function operator(Compiler $compiler) { $compiler->raw('+'); } } -class_alias('Twig_Node_Expression_Unary_Pos', 'Twig\Node\Expression\Unary\PosUnary', false); +class_alias('Twig\Node\Expression\Unary\PosUnary', 'Twig_Node_Expression_Unary_Pos'); diff --git a/system/libs/Twig/Node/Flush.php b/system/libs/Twig/Node/FlushNode.php old mode 100755 new mode 100644 similarity index 67% rename from system/libs/Twig/Node/Flush.php rename to system/libs/Twig/Node/FlushNode.php index fcc461ac..6cbc489a --- a/system/libs/Twig/Node/Flush.php +++ b/system/libs/Twig/Node/FlushNode.php @@ -9,19 +9,23 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; + /** * Represents a flush node. * * @author Fabien Potencier */ -class Twig_Node_Flush extends Twig_Node +class FlushNode extends Node { public function __construct($lineno, $tag) { - parent::__construct(array(), array(), $lineno, $tag); + parent::__construct([], [], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->addDebugInfo($this) @@ -30,4 +34,4 @@ class Twig_Node_Flush extends Twig_Node } } -class_alias('Twig_Node_Flush', 'Twig\Node\FlushNode', false); +class_alias('Twig\Node\FlushNode', 'Twig_Node_Flush'); diff --git a/system/libs/Twig/Node/ForLoop.php b/system/libs/Twig/Node/ForLoopNode.php old mode 100755 new mode 100644 similarity index 81% rename from system/libs/Twig/Node/ForLoop.php rename to system/libs/Twig/Node/ForLoopNode.php index 06477cf1..39020935 --- a/system/libs/Twig/Node/ForLoop.php +++ b/system/libs/Twig/Node/ForLoopNode.php @@ -9,19 +9,23 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; + /** * Internal node used by the for node. * * @author Fabien Potencier */ -class Twig_Node_ForLoop extends Twig_Node +class ForLoopNode extends Node { public function __construct($lineno, $tag = null) { - parent::__construct(array(), array('with_loop' => false, 'ifexpr' => false, 'else' => false), $lineno, $tag); + parent::__construct([], ['with_loop' => false, 'ifexpr' => false, 'else' => false], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { if ($this->getAttribute('else')) { $compiler->write("\$context['_iterated'] = true;\n"); @@ -49,4 +53,4 @@ class Twig_Node_ForLoop extends Twig_Node } } -class_alias('Twig_Node_ForLoop', 'Twig\Node\ForLoopNode', false); +class_alias('Twig\Node\ForLoopNode', 'Twig_Node_ForLoop'); diff --git a/system/libs/Twig/Node/For.php b/system/libs/Twig/Node/ForNode.php old mode 100755 new mode 100644 similarity index 75% rename from system/libs/Twig/Node/For.php rename to system/libs/Twig/Node/ForNode.php index 914b70c9..49409a39 --- a/system/libs/Twig/Node/For.php +++ b/system/libs/Twig/Node/ForNode.php @@ -10,32 +10,38 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\AssignNameExpression; + /** * Represents a for node. * * @author Fabien Potencier */ -class Twig_Node_For extends Twig_Node +class ForNode extends Node { protected $loop; - public function __construct(Twig_Node_Expression_AssignName $keyTarget, Twig_Node_Expression_AssignName $valueTarget, Twig_Node_Expression $seq, Twig_Node_Expression $ifexpr = null, Twig_NodeInterface $body, Twig_NodeInterface $else = null, $lineno, $tag = null) + public function __construct(AssignNameExpression $keyTarget, AssignNameExpression $valueTarget, AbstractExpression $seq, AbstractExpression $ifexpr = null, \Twig_NodeInterface $body, \Twig_NodeInterface $else = null, $lineno, $tag = null) { - $body = new Twig_Node(array($body, $this->loop = new Twig_Node_ForLoop($lineno, $tag))); + $body = new Node([$body, $this->loop = new ForLoopNode($lineno, $tag)]); if (null !== $ifexpr) { - $body = new Twig_Node_If(new Twig_Node(array($ifexpr, $body)), null, $lineno, $tag); + $body = new IfNode(new Node([$ifexpr, $body]), null, $lineno, $tag); } - $nodes = array('key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body); + $nodes = ['key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body]; if (null !== $else) { $nodes['else'] = $else; } - parent::__construct($nodes, array('with_loop' => true, 'ifexpr' => null !== $ifexpr), $lineno, $tag); + parent::__construct($nodes, ['with_loop' => true, 'ifexpr' => null !== $ifexpr], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->addDebugInfo($this) @@ -51,17 +57,17 @@ class Twig_Node_For extends Twig_Node if ($this->getAttribute('with_loop')) { $compiler - ->write("\$context['loop'] = array(\n") + ->write("\$context['loop'] = [\n") ->write(" 'parent' => \$context['_parent'],\n") ->write(" 'index0' => 0,\n") ->write(" 'index' => 1,\n") ->write(" 'first' => true,\n") - ->write(");\n") + ->write("];\n") ; if (!$this->getAttribute('ifexpr')) { $compiler - ->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable)) {\n") + ->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof \Countable)) {\n") ->indent() ->write("\$length = count(\$context['_seq']);\n") ->write("\$context['loop']['revindex0'] = \$length - 1;\n") @@ -110,4 +116,4 @@ class Twig_Node_For extends Twig_Node } } -class_alias('Twig_Node_For', 'Twig\Node\ForNode', false); +class_alias('Twig\Node\ForNode', 'Twig_Node_For'); diff --git a/system/libs/Twig/Node/If.php b/system/libs/Twig/Node/IfNode.php old mode 100755 new mode 100644 similarity index 73% rename from system/libs/Twig/Node/If.php rename to system/libs/Twig/Node/IfNode.php index d82edec7..4836d91f --- a/system/libs/Twig/Node/If.php +++ b/system/libs/Twig/Node/IfNode.php @@ -10,27 +10,31 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; + /** * Represents an if node. * * @author Fabien Potencier */ -class Twig_Node_If extends Twig_Node +class IfNode extends Node { - public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else = null, $lineno, $tag = null) + public function __construct(\Twig_NodeInterface $tests, \Twig_NodeInterface $else = null, $lineno, $tag = null) { - $nodes = array('tests' => $tests); + $nodes = ['tests' => $tests]; if (null !== $else) { $nodes['else'] = $else; } - parent::__construct($nodes, array(), $lineno, $tag); + parent::__construct($nodes, [], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler->addDebugInfo($this); - for ($i = 0, $count = count($this->getNode('tests')); $i < $count; $i += 2) { + for ($i = 0, $count = \count($this->getNode('tests')); $i < $count; $i += 2) { if ($i > 0) { $compiler ->outdent() @@ -65,4 +69,4 @@ class Twig_Node_If extends Twig_Node } } -class_alias('Twig_Node_If', 'Twig\Node\IfNode', false); +class_alias('Twig\Node\IfNode', 'Twig_Node_If'); diff --git a/system/libs/Twig/Node/Import.php b/system/libs/Twig/Node/ImportNode.php old mode 100755 new mode 100644 similarity index 58% rename from system/libs/Twig/Node/Import.php rename to system/libs/Twig/Node/ImportNode.php index c77e320b..236db890 --- a/system/libs/Twig/Node/Import.php +++ b/system/libs/Twig/Node/ImportNode.php @@ -9,19 +9,25 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\NameExpression; + /** * Represents an import node. * * @author Fabien Potencier */ -class Twig_Node_Import extends Twig_Node +class ImportNode extends Node { - public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $var, $lineno, $tag = null) + public function __construct(AbstractExpression $expr, AbstractExpression $var, $lineno, $tag = null) { - parent::__construct(array('expr' => $expr, 'var' => $var), array(), $lineno, $tag); + parent::__construct(['expr' => $expr, 'var' => $var], [], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->addDebugInfo($this) @@ -30,7 +36,7 @@ class Twig_Node_Import extends Twig_Node ->raw(' = ') ; - if ($this->getNode('expr') instanceof Twig_Node_Expression_Name && '_self' === $this->getNode('expr')->getAttribute('name')) { + if ($this->getNode('expr') instanceof NameExpression && '_self' === $this->getNode('expr')->getAttribute('name')) { $compiler->raw('$this'); } else { $compiler @@ -40,7 +46,7 @@ class Twig_Node_Import extends Twig_Node ->repr($this->getTemplateName()) ->raw(', ') ->repr($this->getTemplateLine()) - ->raw(')') + ->raw(')->unwrap()') ; } @@ -48,4 +54,4 @@ class Twig_Node_Import extends Twig_Node } } -class_alias('Twig_Node_Import', 'Twig\Node\ImportNode', false); +class_alias('Twig\Node\ImportNode', 'Twig_Node_Import'); diff --git a/system/libs/Twig/Node/Include.php b/system/libs/Twig/Node/Include.php deleted file mode 100755 index 2a5114cb..00000000 --- a/system/libs/Twig/Node/Include.php +++ /dev/null @@ -1,90 +0,0 @@ - - */ -class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface -{ - public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null) - { - $nodes = array('expr' => $expr); - if (null !== $variables) { - $nodes['variables'] = $variables; - } - - parent::__construct($nodes, array('only' => (bool) $only, 'ignore_missing' => (bool) $ignoreMissing), $lineno, $tag); - } - - public function compile(Twig_Compiler $compiler) - { - $compiler->addDebugInfo($this); - - if ($this->getAttribute('ignore_missing')) { - $compiler - ->write("try {\n") - ->indent() - ; - } - - $this->addGetTemplate($compiler); - - $compiler->raw('->display('); - - $this->addTemplateArguments($compiler); - - $compiler->raw(");\n"); - - if ($this->getAttribute('ignore_missing')) { - $compiler - ->outdent() - ->write("} catch (Twig_Error_Loader \$e) {\n") - ->indent() - ->write("// ignore missing template\n") - ->outdent() - ->write("}\n\n") - ; - } - } - - protected function addGetTemplate(Twig_Compiler $compiler) - { - $compiler - ->write('$this->loadTemplate(') - ->subcompile($this->getNode('expr')) - ->raw(', ') - ->repr($this->getTemplateName()) - ->raw(', ') - ->repr($this->getTemplateLine()) - ->raw(')') - ; - } - - protected function addTemplateArguments(Twig_Compiler $compiler) - { - if (!$this->hasNode('variables')) { - $compiler->raw(false === $this->getAttribute('only') ? '$context' : 'array()'); - } elseif (false === $this->getAttribute('only')) { - $compiler - ->raw('array_merge($context, ') - ->subcompile($this->getNode('variables')) - ->raw(')') - ; - } else { - $compiler->subcompile($this->getNode('variables')); - } - } -} - -class_alias('Twig_Node_Include', 'Twig\Node\IncludeNode', false); diff --git a/system/libs/Twig/Node/IncludeNode.php b/system/libs/Twig/Node/IncludeNode.php new file mode 100644 index 00000000..544db81e --- /dev/null +++ b/system/libs/Twig/Node/IncludeNode.php @@ -0,0 +1,108 @@ + + */ +class IncludeNode extends Node implements NodeOutputInterface +{ + public function __construct(AbstractExpression $expr, AbstractExpression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null) + { + $nodes = ['expr' => $expr]; + if (null !== $variables) { + $nodes['variables'] = $variables; + } + + parent::__construct($nodes, ['only' => (bool) $only, 'ignore_missing' => (bool) $ignoreMissing], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler->addDebugInfo($this); + + if ($this->getAttribute('ignore_missing')) { + $template = $compiler->getVarName(); + + $compiler + ->write(sprintf("$%s = null;\n", $template)) + ->write("try {\n") + ->indent() + ->write(sprintf('$%s = ', $template)) + ; + + $this->addGetTemplate($compiler); + + $compiler + ->raw(";\n") + ->outdent() + ->write("} catch (LoaderError \$e) {\n") + ->indent() + ->write("// ignore missing template\n") + ->outdent() + ->write("}\n") + ->write(sprintf("if ($%s) {\n", $template)) + ->indent() + ->write(sprintf('$%s->display(', $template)) + ; + $this->addTemplateArguments($compiler); + $compiler + ->raw(");\n") + ->outdent() + ->write("}\n") + ; + } else { + $this->addGetTemplate($compiler); + $compiler->raw('->display('); + $this->addTemplateArguments($compiler); + $compiler->raw(");\n"); + } + } + + protected function addGetTemplate(Compiler $compiler) + { + $compiler + ->write('$this->loadTemplate(') + ->subcompile($this->getNode('expr')) + ->raw(', ') + ->repr($this->getTemplateName()) + ->raw(', ') + ->repr($this->getTemplateLine()) + ->raw(')') + ; + } + + protected function addTemplateArguments(Compiler $compiler) + { + if (!$this->hasNode('variables')) { + $compiler->raw(false === $this->getAttribute('only') ? '$context' : '[]'); + } elseif (false === $this->getAttribute('only')) { + $compiler + ->raw('twig_array_merge($context, ') + ->subcompile($this->getNode('variables')) + ->raw(')') + ; + } else { + $compiler->raw('twig_to_array('); + $compiler->subcompile($this->getNode('variables')); + $compiler->raw(')'); + } + } +} + +class_alias('Twig\Node\IncludeNode', 'Twig_Node_Include'); diff --git a/system/libs/Twig/Node/Macro.php b/system/libs/Twig/Node/MacroNode.php old mode 100755 new mode 100644 similarity index 63% rename from system/libs/Twig/Node/Macro.php rename to system/libs/Twig/Node/MacroNode.php index 3cf54977..6eb67955 --- a/system/libs/Twig/Node/Macro.php +++ b/system/libs/Twig/Node/MacroNode.php @@ -9,34 +9,39 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; +use Twig\Error\SyntaxError; + /** * Represents a macro node. * * @author Fabien Potencier */ -class Twig_Node_Macro extends Twig_Node +class MacroNode extends Node { const VARARGS_NAME = 'varargs'; - public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null) + public function __construct($name, \Twig_NodeInterface $body, \Twig_NodeInterface $arguments, $lineno, $tag = null) { foreach ($arguments as $argumentName => $argument) { if (self::VARARGS_NAME === $argumentName) { - throw new Twig_Error_Syntax(sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.', self::VARARGS_NAME, $name, self::VARARGS_NAME), $argument->getTemplateLine()); + 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(), $argument->getSourceContext()); } } - parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag); + parent::__construct(['body' => $body, 'arguments' => $arguments], ['name' => $name], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->addDebugInfo($this) ->write(sprintf('public function get%s(', $this->getAttribute('name'))) ; - $count = count($this->getNode('arguments')); + $count = \count($this->getNode('arguments')); $pos = 0; foreach ($this->getNode('arguments') as $name => $default) { $compiler @@ -49,7 +54,7 @@ class Twig_Node_Macro extends Twig_Node } } - if (PHP_VERSION_ID >= 50600) { + if (\PHP_VERSION_ID >= 50600) { if ($count) { $compiler->raw(', '); } @@ -64,7 +69,7 @@ class Twig_Node_Macro extends Twig_Node ; $compiler - ->write("\$context = \$this->env->mergeGlobals(array(\n") + ->write("\$context = \$this->env->mergeGlobals([\n") ->indent() ; @@ -83,7 +88,7 @@ class Twig_Node_Macro extends Twig_Node ->raw(' => ') ; - if (PHP_VERSION_ID >= 50600) { + if (\PHP_VERSION_ID >= 50600) { $compiler->raw("\$__varargs__,\n"); } else { $compiler @@ -91,35 +96,41 @@ class Twig_Node_Macro extends Twig_Node ->repr($count) ->raw(' ? array_slice(func_get_args(), ') ->repr($count) - ->raw(") : array(),\n") + ->raw(") : [],\n") ; } $compiler ->outdent() - ->write("));\n\n") - ->write("\$blocks = array();\n\n") - ->write("ob_start();\n") + ->write("]);\n\n") + ->write("\$blocks = [];\n\n") + ; + if ($compiler->getEnvironment()->isDebug()) { + $compiler->write("ob_start();\n"); + } else { + $compiler->write("ob_start(function () { return ''; });\n"); + } + $compiler ->write("try {\n") ->indent() ->subcompile($this->getNode('body')) ->outdent() - ->write("} catch (Exception \$e) {\n") + ->write("} catch (\Exception \$e) {\n") ->indent() ->write("ob_end_clean();\n\n") ->write("throw \$e;\n") ->outdent() - ->write("} catch (Throwable \$e) {\n") + ->write("} catch (\Throwable \$e) {\n") ->indent() ->write("ob_end_clean();\n\n") ->write("throw \$e;\n") ->outdent() ->write("}\n\n") - ->write("return ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset());\n") + ->write("return ('' === \$tmp = ob_get_clean()) ? '' : new Markup(\$tmp, \$this->env->getCharset());\n") ->outdent() ->write("}\n\n") ; } } -class_alias('Twig_Node_Macro', 'Twig\Node\MacroNode', false); +class_alias('Twig\Node\MacroNode', 'Twig_Node_Macro'); diff --git a/system/libs/Twig/Node/Module.php b/system/libs/Twig/Node/ModuleNode.php old mode 100755 new mode 100644 similarity index 64% rename from system/libs/Twig/Node/Module.php rename to system/libs/Twig/Node/ModuleNode.php index 5cd8d050..aab2aa33 --- a/system/libs/Twig/Node/Module.php +++ b/system/libs/Twig/Node/ModuleNode.php @@ -10,6 +10,13 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Source; + /** * Represents a module node. * @@ -19,46 +26,45 @@ * * @author Fabien Potencier */ -class Twig_Node_Module extends Twig_Node +class ModuleNode extends Node { - private $source; - - public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $name, $source = '') + public function __construct(\Twig_NodeInterface $body, AbstractExpression $parent = null, \Twig_NodeInterface $blocks, \Twig_NodeInterface $macros, \Twig_NodeInterface $traits, $embeddedTemplates, $name, $source = '') { - if (!$name instanceof Twig_Source) { - @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); - $this->source = new Twig_Source($source, $name); + if (!$name instanceof Source) { + @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); + $source = new Source($source, $name); } else { - $this->source = $name; + $source = $name; } - $nodes = array( + $nodes = [ 'body' => $body, 'blocks' => $blocks, 'macros' => $macros, 'traits' => $traits, - 'display_start' => new Twig_Node(), - 'display_end' => new Twig_Node(), - 'constructor_start' => new Twig_Node(), - 'constructor_end' => new Twig_Node(), - 'class_end' => new Twig_Node(), - ); + 'display_start' => new Node(), + 'display_end' => new Node(), + 'constructor_start' => new Node(), + 'constructor_end' => new Node(), + 'class_end' => new Node(), + ]; if (null !== $parent) { $nodes['parent'] = $parent; } // embedded templates are set as attributes so that they are only visited once by the visitors - parent::__construct($nodes, array( + parent::__construct($nodes, [ // source to be remove in 2.0 - 'source' => $this->source->getCode(), + 'source' => $source->getCode(), // filename to be remove in 2.0 (use getTemplateName() instead) - 'filename' => $this->source->getName(), + 'filename' => $source->getName(), 'index' => null, 'embedded_templates' => $embeddedTemplates, - ), 1); + ], 1); // populate the template name of all node children - $this->setTemplateName($this->source->getName()); + $this->setTemplateName($source->getName()); + $this->setSourceContext($source); } public function setIndex($index) @@ -66,7 +72,7 @@ class Twig_Node_Module extends Twig_Node $this->setAttribute('index', $index); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $this->compileTemplate($compiler); @@ -75,7 +81,7 @@ class Twig_Node_Module extends Twig_Node } } - protected function compileTemplate(Twig_Compiler $compiler) + protected function compileTemplate(Compiler $compiler) { if (!$this->getAttribute('index')) { $compiler->write('compileClassHeader($compiler); if ( - count($this->getNode('blocks')) - || count($this->getNode('traits')) + \count($this->getNode('blocks')) + || \count($this->getNode('traits')) || !$this->hasNode('parent') - || $this->getNode('parent') instanceof Twig_Node_Expression_Constant - || count($this->getNode('constructor_start')) - || count($this->getNode('constructor_end')) + || $this->getNode('parent') instanceof ConstantExpression + || \count($this->getNode('constructor_start')) + || \count($this->getNode('constructor_end')) ) { $this->compileConstructor($compiler); } @@ -115,7 +121,7 @@ class Twig_Node_Module extends Twig_Node $this->compileClassFooter($compiler); } - protected function compileGetParent(Twig_Compiler $compiler) + protected function compileGetParent(Compiler $compiler) { if (!$this->hasNode('parent')) { return; @@ -129,14 +135,14 @@ class Twig_Node_Module extends Twig_Node ->write('return ') ; - if ($parent instanceof Twig_Node_Expression_Constant) { + if ($parent instanceof ConstantExpression) { $compiler->subcompile($parent); } else { $compiler ->raw('$this->loadTemplate(') ->subcompile($parent) ->raw(', ') - ->repr($this->source->getName()) + ->repr($this->getSourceContext()->getName()) ->raw(', ') ->repr($parent->getTemplateLine()) ->raw(')') @@ -150,23 +156,39 @@ class Twig_Node_Module extends Twig_Node ; } - protected function compileClassHeader(Twig_Compiler $compiler) + protected function compileClassHeader(Compiler $compiler) { $compiler ->write("\n\n") + ; + if (!$this->getAttribute('index')) { + $compiler + ->write("use Twig\Environment;\n") + ->write("use Twig\Error\LoaderError;\n") + ->write("use Twig\Error\RuntimeError;\n") + ->write("use Twig\Markup;\n") + ->write("use Twig\Sandbox\SecurityError;\n") + ->write("use Twig\Sandbox\SecurityNotAllowedTagError;\n") + ->write("use Twig\Sandbox\SecurityNotAllowedFilterError;\n") + ->write("use Twig\Sandbox\SecurityNotAllowedFunctionError;\n") + ->write("use Twig\Source;\n") + ->write("use Twig\Template;\n\n") + ; + } + $compiler // if the template name contains */, add a blank to avoid a PHP parse error - ->write('/* '.str_replace('*/', '* /', $this->source->getName())." */\n") - ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->source->getName(), $this->getAttribute('index'))) + ->write('/* '.str_replace('*/', '* /', $this->getSourceContext()->getName())." */\n") + ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getSourceContext()->getName(), $this->getAttribute('index'))) ->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass())) ->write("{\n") ->indent() ; } - protected function compileConstructor(Twig_Compiler $compiler) + protected function compileConstructor(Compiler $compiler) { $compiler - ->write("public function __construct(Twig_Environment \$env)\n", "{\n") + ->write("public function __construct(Environment \$env)\n", "{\n") ->indent() ->subcompile($this->getNode('constructor_start')) ->write("parent::__construct(\$env);\n\n") @@ -175,32 +197,24 @@ class Twig_Node_Module extends Twig_Node // parent if (!$this->hasNode('parent')) { $compiler->write("\$this->parent = false;\n\n"); - } elseif (($parent = $this->getNode('parent')) && $parent instanceof Twig_Node_Expression_Constant) { - $compiler - ->addDebugInfo($parent) - ->write('$this->parent = $this->loadTemplate(') - ->subcompile($parent) - ->raw(', ') - ->repr($this->source->getName()) - ->raw(', ') - ->repr($parent->getTemplateLine()) - ->raw(");\n") - ; } - $countTraits = count($this->getNode('traits')); + $countTraits = \count($this->getNode('traits')); if ($countTraits) { // traits foreach ($this->getNode('traits') as $i => $trait) { $this->compileLoadTemplate($compiler, $trait->getNode('template'), sprintf('$_trait_%s', $i)); + $node = $trait->getNode('template'); $compiler - ->addDebugInfo($trait->getNode('template')) + ->addDebugInfo($node) ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i)) ->indent() - ->write("throw new Twig_Error_Runtime('Template \"'.") + ->write("throw new RuntimeError('Template \"'.") ->subcompile($trait->getNode('template')) - ->raw(".'\" cannot be used as a trait.');\n") + ->raw(".'\" cannot be used as a trait.', ") + ->repr($node->getTemplateLine()) + ->raw(", \$this->getSourceContext());\n") ->outdent() ->write("}\n") ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i)) @@ -212,11 +226,13 @@ class Twig_Node_Module extends Twig_Node ->string($key) ->raw("])) {\n") ->indent() - ->write("throw new Twig_Error_Runtime(sprintf('Block ") + ->write("throw new RuntimeError(sprintf('Block ") ->string($key) ->raw(' is not defined in trait ') ->subcompile($trait->getNode('template')) - ->raw(".'));\n") + ->raw(".'), ") + ->repr($node->getTemplateLine()) + ->raw(", \$this->getSourceContext());\n") ->outdent() ->write("}\n\n") @@ -257,11 +273,11 @@ class Twig_Node_Module extends Twig_Node ->write("\$this->blocks = array_merge(\n") ->indent() ->write("\$this->traits,\n") - ->write("array(\n") + ->write("[\n") ; } else { $compiler - ->write("\$this->blocks = array(\n") + ->write("\$this->blocks = [\n") ; } @@ -272,30 +288,35 @@ class Twig_Node_Module extends Twig_Node foreach ($this->getNode('blocks') as $name => $node) { $compiler - ->write(sprintf("'%s' => array(\$this, 'block_%s'),\n", $name, $name)) + ->write(sprintf("'%s' => [\$this, 'block_%s'],\n", $name, $name)) ; } if ($countTraits) { $compiler ->outdent() - ->write(")\n") + ->write("]\n") + ->outdent() + ->write(");\n") + ; + } else { + $compiler + ->outdent() + ->write("];\n") ; } $compiler - ->outdent() - ->write(");\n") - ->outdent() ->subcompile($this->getNode('constructor_end')) + ->outdent() ->write("}\n\n") ; } - protected function compileDisplay(Twig_Compiler $compiler) + protected function compileDisplay(Compiler $compiler) { $compiler - ->write("protected function doDisplay(array \$context, array \$blocks = array())\n", "{\n") + ->write("protected function doDisplay(array \$context, array \$blocks = [])\n", "{\n") ->indent() ->subcompile($this->getNode('display_start')) ->subcompile($this->getNode('body')) @@ -303,8 +324,18 @@ class Twig_Node_Module extends Twig_Node if ($this->hasNode('parent')) { $parent = $this->getNode('parent'); + $compiler->addDebugInfo($parent); - if ($parent instanceof Twig_Node_Expression_Constant) { + if ($parent instanceof ConstantExpression) { + $compiler + ->write('$this->parent = $this->loadTemplate(') + ->subcompile($parent) + ->raw(', ') + ->repr($this->getSourceContext()->getName()) + ->raw(', ') + ->repr($parent->getTemplateLine()) + ->raw(");\n") + ; $compiler->write('$this->parent'); } else { $compiler->write('$this->getParent($context)'); @@ -319,7 +350,7 @@ class Twig_Node_Module extends Twig_Node ; } - protected function compileClassFooter(Twig_Compiler $compiler) + protected function compileClassFooter(Compiler $compiler) { $compiler ->subcompile($this->getNode('class_end')) @@ -328,25 +359,25 @@ class Twig_Node_Module extends Twig_Node ; } - protected function compileMacros(Twig_Compiler $compiler) + protected function compileMacros(Compiler $compiler) { $compiler->subcompile($this->getNode('macros')); } - protected function compileGetTemplateName(Twig_Compiler $compiler) + protected function compileGetTemplateName(Compiler $compiler) { $compiler ->write("public function getTemplateName()\n", "{\n") ->indent() ->write('return ') - ->repr($this->source->getName()) + ->repr($this->getSourceContext()->getName()) ->raw(";\n") ->outdent() ->write("}\n\n") ; } - protected function compileIsTraitable(Twig_Compiler $compiler) + protected function compileIsTraitable(Compiler $compiler) { // A template can be used as a trait if: // * it has no parent @@ -355,28 +386,28 @@ class Twig_Node_Module extends Twig_Node // // Put another way, a template can be used as a trait if it // only contains blocks and use statements. - $traitable = !$this->hasNode('parent') && 0 === count($this->getNode('macros')); + $traitable = !$this->hasNode('parent') && 0 === \count($this->getNode('macros')); if ($traitable) { - if ($this->getNode('body') instanceof Twig_Node_Body) { + if ($this->getNode('body') instanceof BodyNode) { $nodes = $this->getNode('body')->getNode(0); } else { $nodes = $this->getNode('body'); } - if (!count($nodes)) { - $nodes = new Twig_Node(array($nodes)); + if (!\count($nodes)) { + $nodes = new Node([$nodes]); } foreach ($nodes as $node) { - if (!count($node)) { + if (!\count($node)) { continue; } - if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) { + if ($node instanceof TextNode && ctype_space($node->getAttribute('data'))) { continue; } - if ($node instanceof Twig_Node_BlockReference) { + if ($node instanceof BlockReferenceNode) { continue; } @@ -398,7 +429,7 @@ class Twig_Node_Module extends Twig_Node ; } - protected function compileDebugInfo(Twig_Compiler $compiler) + protected function compileDebugInfo(Compiler $compiler) { $compiler ->write("public function getDebugInfo()\n", "{\n") @@ -409,7 +440,7 @@ class Twig_Node_Module extends Twig_Node ; } - protected function compileGetSource(Twig_Compiler $compiler) + protected function compileGetSource(Compiler $compiler) { $compiler ->write("/** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */\n") @@ -423,26 +454,26 @@ class Twig_Node_Module extends Twig_Node ; } - protected function compileGetSourceContext(Twig_Compiler $compiler) + protected function compileGetSourceContext(Compiler $compiler) { $compiler ->write("public function getSourceContext()\n", "{\n") ->indent() - ->write('return new Twig_Source(') - ->string($compiler->getEnvironment()->isDebug() ? $this->source->getCode() : '') + ->write('return new Source(') + ->string($compiler->getEnvironment()->isDebug() ? $this->getSourceContext()->getCode() : '') ->raw(', ') - ->string($this->source->getName()) + ->string($this->getSourceContext()->getName()) ->raw(', ') - ->string($this->source->getPath()) + ->string($this->getSourceContext()->getPath()) ->raw(");\n") ->outdent() ->write("}\n") ; } - protected function compileLoadTemplate(Twig_Compiler $compiler, $node, $var) + protected function compileLoadTemplate(Compiler $compiler, $node, $var) { - if ($node instanceof Twig_Node_Expression_Constant) { + if ($node instanceof ConstantExpression) { $compiler ->write(sprintf('%s = $this->loadTemplate(', $var)) ->subcompile($node) @@ -453,9 +484,9 @@ class Twig_Node_Module extends Twig_Node ->raw(");\n") ; } else { - throw new LogicException('Trait templates can only be constant nodes.'); + throw new \LogicException('Trait templates can only be constant nodes.'); } } } -class_alias('Twig_Node_Module', 'Twig\Node\ModuleNode', false); +class_alias('Twig\Node\ModuleNode', 'Twig_Node_Module'); diff --git a/system/libs/Twig/Node.php b/system/libs/Twig/Node/Node.php old mode 100755 new mode 100644 similarity index 71% rename from system/libs/Twig/Node.php rename to system/libs/Twig/Node/Node.php index 89ada144..c890feb7 --- a/system/libs/Twig/Node.php +++ b/system/libs/Twig/Node/Node.php @@ -10,12 +10,17 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; +use Twig\Source; + /** * Represents a node in the AST. * * @author Fabien Potencier */ -class Twig_Node implements Twig_NodeInterface +class Node implements \Twig_NodeInterface { protected $nodes; protected $attributes; @@ -23,23 +28,19 @@ class Twig_Node implements Twig_NodeInterface protected $tag; private $name; + private $sourceContext; /** - * Constructor. - * - * The nodes are automatically made available as properties ($this->node). - * The attributes are automatically made available as array items ($this['name']). - * * @param array $nodes An array of named nodes * @param array $attributes An array of attributes (should not be nodes) * @param int $lineno The line number * @param string $tag The tag name associated with the Node */ - public function __construct(array $nodes = array(), array $attributes = array(), $lineno = 0, $tag = null) + public function __construct(array $nodes = [], array $attributes = [], $lineno = 0, $tag = null) { foreach ($nodes as $name => $node) { - if (!$node instanceof Twig_NodeInterface) { - @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); + if (!$node instanceof \Twig_NodeInterface) { + @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); } } $this->nodes = $nodes; @@ -50,17 +51,17 @@ class Twig_Node implements Twig_NodeInterface public function __toString() { - $attributes = array(); + $attributes = []; foreach ($this->attributes as $name => $value) { $attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true))); } - $repr = array(get_class($this).'('.implode(', ', $attributes)); + $repr = [\get_class($this).'('.implode(', ', $attributes)]; - if (count($this->nodes)) { + if (\count($this->nodes)) { foreach ($this->nodes as $name => $node) { - $len = strlen($name) + 4; - $noderepr = array(); + $len = \strlen($name) + 4; + $noderepr = []; foreach (explode("\n", (string) $node) as $line) { $noderepr[] = str_repeat(' ', $len).$line; } @@ -83,12 +84,12 @@ class Twig_Node implements Twig_NodeInterface { @trigger_error(sprintf('%s is deprecated since version 1.16.1 and will be removed in 2.0.', __METHOD__), E_USER_DEPRECATED); - $dom = new DOMDocument('1.0', 'UTF-8'); + $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->formatOutput = true; $dom->appendChild($xml = $dom->createElement('twig')); $xml->appendChild($node = $dom->createElement('node')); - $node->setAttribute('class', get_class($this)); + $node->setAttribute('class', \get_class($this)); foreach ($this->attributes as $name => $value) { $node->appendChild($attribute = $dom->createElement('attribute')); @@ -111,7 +112,7 @@ class Twig_Node implements Twig_NodeInterface return $asDom ? $dom : $dom->saveXML(); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { foreach ($this->nodes as $node) { $node->compile($compiler); @@ -143,7 +144,7 @@ class Twig_Node implements Twig_NodeInterface */ public function hasAttribute($name) { - return array_key_exists($name, $this->attributes); + return \array_key_exists($name, $this->attributes); } /** @@ -151,8 +152,8 @@ class Twig_Node implements Twig_NodeInterface */ public function getAttribute($name) { - if (!array_key_exists($name, $this->attributes)) { - throw new LogicException(sprintf('Attribute "%s" does not exist for Node "%s".', $name, get_class($this))); + if (!\array_key_exists($name, $this->attributes)) { + throw new \LogicException(sprintf('Attribute "%s" does not exist for Node "%s".', $name, \get_class($this))); } return $this->attributes[$name]; @@ -177,16 +178,16 @@ class Twig_Node implements Twig_NodeInterface */ public function hasNode($name) { - return array_key_exists($name, $this->nodes); + return \array_key_exists($name, $this->nodes); } /** - * @return Twig_Node + * @return Node */ public function getNode($name) { - if (!array_key_exists($name, $this->nodes)) { - throw new LogicException(sprintf('Node "%s" does not exist for Node "%s".', $name, get_class($this))); + if (!\array_key_exists($name, $this->nodes)) { + throw new \LogicException(sprintf('Node "%s" does not exist for Node "%s".', $name, \get_class($this))); } return $this->nodes[$name]; @@ -194,8 +195,8 @@ class Twig_Node implements Twig_NodeInterface public function setNode($name, $node = null) { - if (!$node instanceof Twig_NodeInterface) { - @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); + if (!$node instanceof \Twig_NodeInterface) { + @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); } $this->nodes[$name] = $node; @@ -208,12 +209,12 @@ class Twig_Node implements Twig_NodeInterface public function count() { - return count($this->nodes); + return \count($this->nodes); } public function getIterator() { - return new ArrayIterator($this->nodes); + return new \ArrayIterator($this->nodes); } public function setTemplateName($name) @@ -231,6 +232,21 @@ class Twig_Node implements Twig_NodeInterface return $this->name; } + public function setSourceContext(Source $source) + { + $this->sourceContext = $source; + foreach ($this->nodes as $node) { + if ($node instanceof Node) { + $node->setSourceContext($source); + } + } + } + + public function getSourceContext() + { + return $this->sourceContext; + } + /** * @deprecated since 1.27 (to be removed in 2.0) */ @@ -252,5 +268,7 @@ class Twig_Node implements Twig_NodeInterface } } -class_alias('Twig_Node', 'Twig\Node\Node', false); -class_exists('Twig_Compiler'); +class_alias('Twig\Node\Node', 'Twig_Node'); + +// Ensure that the aliased name is loaded to keep BC for classes implementing the typehint with the old aliased name. +class_exists('Twig\Compiler'); diff --git a/system/libs/Twig/NodeCaptureInterface.php b/system/libs/Twig/Node/NodeCaptureInterface.php similarity index 72% rename from system/libs/Twig/NodeCaptureInterface.php rename to system/libs/Twig/Node/NodeCaptureInterface.php index 6638834b..474003f3 100644 --- a/system/libs/Twig/NodeCaptureInterface.php +++ b/system/libs/Twig/Node/NodeCaptureInterface.php @@ -9,13 +9,15 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + /** * Represents a node that captures any nested displayable nodes. * * @author Fabien Potencier */ -interface Twig_NodeCaptureInterface +interface NodeCaptureInterface { } -class_alias('Twig_NodeCaptureInterface', 'Twig\Node\NodeCaptureInterface', false); +class_alias('Twig\Node\NodeCaptureInterface', 'Twig_NodeCaptureInterface'); diff --git a/system/libs/Twig/NodeOutputInterface.php b/system/libs/Twig/Node/NodeOutputInterface.php old mode 100755 new mode 100644 similarity index 71% rename from system/libs/Twig/NodeOutputInterface.php rename to system/libs/Twig/Node/NodeOutputInterface.php index 5a8eaa9c..8b046ee7 --- a/system/libs/Twig/NodeOutputInterface.php +++ b/system/libs/Twig/Node/NodeOutputInterface.php @@ -9,13 +9,15 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + /** * Represents a displayable node in the AST. * * @author Fabien Potencier */ -interface Twig_NodeOutputInterface +interface NodeOutputInterface { } -class_alias('Twig_NodeOutputInterface', 'Twig\Node\NodeOutputInterface', false); +class_alias('Twig\Node\NodeOutputInterface', 'Twig_NodeOutputInterface'); diff --git a/system/libs/Twig/Node/Print.php b/system/libs/Twig/Node/PrintNode.php old mode 100755 new mode 100644 similarity index 57% rename from system/libs/Twig/Node/Print.php rename to system/libs/Twig/Node/PrintNode.php index 374db89b..27f1ca42 --- a/system/libs/Twig/Node/Print.php +++ b/system/libs/Twig/Node/PrintNode.php @@ -10,19 +10,24 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; + /** * Represents a node that outputs an expression. * * @author Fabien Potencier */ -class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface +class PrintNode extends Node implements NodeOutputInterface { - public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) + public function __construct(AbstractExpression $expr, $lineno, $tag = null) { - parent::__construct(array('expr' => $expr), array(), $lineno, $tag); + parent::__construct(['expr' => $expr], [], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->addDebugInfo($this) @@ -33,4 +38,4 @@ class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface } } -class_alias('Twig_Node_Print', 'Twig\Node\PrintNode', false); +class_alias('Twig\Node\PrintNode', 'Twig_Node_Print'); diff --git a/system/libs/Twig/Node/Sandbox.php b/system/libs/Twig/Node/SandboxNode.php old mode 100755 new mode 100644 similarity index 51% rename from system/libs/Twig/Node/Sandbox.php rename to system/libs/Twig/Node/SandboxNode.php index 44b30ab9..2d644c3a --- a/system/libs/Twig/Node/Sandbox.php +++ b/system/libs/Twig/Node/SandboxNode.php @@ -9,36 +9,39 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; + /** * Represents a sandbox node. * * @author Fabien Potencier */ -class Twig_Node_Sandbox extends Twig_Node +class SandboxNode extends Node { - public function __construct(Twig_NodeInterface $body, $lineno, $tag = null) + public function __construct(\Twig_NodeInterface $body, $lineno, $tag = null) { - parent::__construct(array('body' => $body), array(), $lineno, $tag); + parent::__construct(['body' => $body], [], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->addDebugInfo($this) - ->write("\$sandbox = \$this->env->getExtension('Twig_Extension_Sandbox');\n") - ->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n") + ->write("if (!\$alreadySandboxed = \$this->sandbox->isSandboxed()) {\n") ->indent() - ->write("\$sandbox->enableSandbox();\n") + ->write("\$this->sandbox->enableSandbox();\n") ->outdent() ->write("}\n") ->subcompile($this->getNode('body')) ->write("if (!\$alreadySandboxed) {\n") ->indent() - ->write("\$sandbox->disableSandbox();\n") + ->write("\$this->sandbox->disableSandbox();\n") ->outdent() ->write("}\n") ; } } -class_alias('Twig_Node_Sandbox', 'Twig\Node\SandboxNode', false); +class_alias('Twig\Node\SandboxNode', 'Twig_Node_Sandbox'); diff --git a/system/libs/Twig/Node/SandboxedPrint.php b/system/libs/Twig/Node/SandboxedPrint.php deleted file mode 100755 index a08f21f5..00000000 --- a/system/libs/Twig/Node/SandboxedPrint.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ -class Twig_Node_SandboxedPrint extends Twig_Node_Print -{ - public function compile(Twig_Compiler $compiler) - { - $compiler - ->addDebugInfo($this) - ->write('echo $this->env->getExtension(\'Twig_Extension_Sandbox\')->ensureToStringAllowed(') - ->subcompile($this->getNode('expr')) - ->raw(");\n") - ; - } - - /** - * Removes node filters. - * - * This is mostly needed when another visitor adds filters (like the escaper one). - * - * @return Twig_Node - */ - protected function removeNodeFilter(Twig_Node $node) - { - if ($node instanceof Twig_Node_Expression_Filter) { - return $this->removeNodeFilter($node->getNode('node')); - } - - return $node; - } -} - -class_alias('Twig_Node_SandboxedPrint', 'Twig\Node\SandboxedPrintNode', false); diff --git a/system/libs/Twig/Node/SandboxedPrintNode.php b/system/libs/Twig/Node/SandboxedPrintNode.php new file mode 100644 index 00000000..2359af91 --- /dev/null +++ b/system/libs/Twig/Node/SandboxedPrintNode.php @@ -0,0 +1,69 @@ + + */ +class SandboxedPrintNode extends PrintNode +{ + public function compile(Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write('echo ') + ; + $expr = $this->getNode('expr'); + if ($expr instanceof ConstantExpression) { + $compiler + ->subcompile($expr) + ->raw(";\n") + ; + } else { + $compiler + ->write('$this->env->getExtension(\'\Twig\Extension\SandboxExtension\')->ensureToStringAllowed(') + ->subcompile($expr) + ->raw(");\n") + ; + } + } + + /** + * Removes node filters. + * + * This is mostly needed when another visitor adds filters (like the escaper one). + * + * @return Node + */ + protected function removeNodeFilter(Node $node) + { + if ($node instanceof FilterExpression) { + return $this->removeNodeFilter($node->getNode('node')); + } + + return $node; + } +} + +class_alias('Twig\Node\SandboxedPrintNode', 'Twig_Node_SandboxedPrint'); diff --git a/system/libs/Twig/Node/Set.php b/system/libs/Twig/Node/SetNode.php old mode 100755 new mode 100644 similarity index 63% rename from system/libs/Twig/Node/Set.php rename to system/libs/Twig/Node/SetNode.php index 6c6743ee..656103b9 --- a/system/libs/Twig/Node/Set.php +++ b/system/libs/Twig/Node/SetNode.php @@ -9,38 +9,43 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; +use Twig\Node\Expression\ConstantExpression; + /** * Represents a set node. * * @author Fabien Potencier */ -class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface +class SetNode extends Node implements NodeCaptureInterface { - public function __construct($capture, Twig_NodeInterface $names, Twig_NodeInterface $values, $lineno, $tag = null) + public function __construct($capture, \Twig_NodeInterface $names, \Twig_NodeInterface $values, $lineno, $tag = null) { - parent::__construct(array('names' => $names, 'values' => $values), array('capture' => $capture, 'safe' => false), $lineno, $tag); + parent::__construct(['names' => $names, 'values' => $values], ['capture' => $capture, 'safe' => false], $lineno, $tag); /* * Optimizes the node when capture is used for a large block of text. * - * {% set foo %}foo{% endset %} is compiled to $context['foo'] = new Twig_Markup("foo"); + * {% set foo %}foo{% endset %} is compiled to $context['foo'] = new Twig\Markup("foo"); */ if ($this->getAttribute('capture')) { $this->setAttribute('safe', true); $values = $this->getNode('values'); - if ($values instanceof Twig_Node_Text) { - $this->setNode('values', new Twig_Node_Expression_Constant($values->getAttribute('data'), $values->getTemplateLine())); + if ($values instanceof TextNode) { + $this->setNode('values', new ConstantExpression($values->getAttribute('data'), $values->getTemplateLine())); $this->setAttribute('capture', false); } } } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler->addDebugInfo($this); - if (count($this->getNode('names')) > 1) { + if (\count($this->getNode('names')) > 1) { $compiler->write('list('); foreach ($this->getNode('names') as $idx => $node) { if ($idx) { @@ -52,8 +57,12 @@ class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface $compiler->raw(')'); } else { if ($this->getAttribute('capture')) { + if ($compiler->getEnvironment()->isDebug()) { + $compiler->write("ob_start();\n"); + } else { + $compiler->write("ob_start(function () { return ''; });\n"); + } $compiler - ->write("ob_start();\n") ->subcompile($this->getNode('values')) ; } @@ -61,15 +70,15 @@ class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface $compiler->subcompile($this->getNode('names'), false); if ($this->getAttribute('capture')) { - $compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())"); + $compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new Markup(\$tmp, \$this->env->getCharset())"); } } if (!$this->getAttribute('capture')) { $compiler->raw(' = '); - if (count($this->getNode('names')) > 1) { - $compiler->write('array('); + if (\count($this->getNode('names')) > 1) { + $compiler->write('['); foreach ($this->getNode('values') as $idx => $value) { if ($idx) { $compiler->raw(', '); @@ -77,13 +86,13 @@ class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface $compiler->subcompile($value); } - $compiler->raw(')'); + $compiler->raw(']'); } else { if ($this->getAttribute('safe')) { $compiler ->raw("('' === \$tmp = ") ->subcompile($this->getNode('values')) - ->raw(") ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())") + ->raw(") ? '' : new Markup(\$tmp, \$this->env->getCharset())") ; } else { $compiler->subcompile($this->getNode('values')); @@ -95,4 +104,4 @@ class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface } } -class_alias('Twig_Node_Set', 'Twig\Node\SetNode', false); +class_alias('Twig\Node\SetNode', 'Twig_Node_Set'); diff --git a/system/libs/Twig/Node/SetTemp.php b/system/libs/Twig/Node/SetTempNode.php old mode 100755 new mode 100644 similarity index 74% rename from system/libs/Twig/Node/SetTemp.php rename to system/libs/Twig/Node/SetTempNode.php index 996fdcde..918fb991 --- a/system/libs/Twig/Node/SetTemp.php +++ b/system/libs/Twig/Node/SetTempNode.php @@ -9,17 +9,21 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; + /** * @internal */ -class Twig_Node_SetTemp extends Twig_Node +class SetTempNode extends Node { public function __construct($name, $lineno) { - parent::__construct(array(), array('name' => $name), $lineno); + parent::__construct([], ['name' => $name], $lineno); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $name = $this->getAttribute('name'); $compiler @@ -37,4 +41,4 @@ class Twig_Node_SetTemp extends Twig_Node } } -class_alias('Twig_Node_SetTemp', 'Twig\Node\SetTempNode', false); +class_alias('Twig\Node\SetTempNode', 'Twig_Node_SetTemp'); diff --git a/system/libs/Twig/Node/Spaceless.php b/system/libs/Twig/Node/Spaceless.php deleted file mode 100755 index 76f90cde..00000000 --- a/system/libs/Twig/Node/Spaceless.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -class Twig_Node_Spaceless extends Twig_Node -{ - public function __construct(Twig_NodeInterface $body, $lineno, $tag = 'spaceless') - { - parent::__construct(array('body' => $body), array(), $lineno, $tag); - } - - public function compile(Twig_Compiler $compiler) - { - $compiler - ->addDebugInfo($this) - ->write("ob_start();\n") - ->subcompile($this->getNode('body')) - ->write("echo trim(preg_replace('/>\s+<', ob_get_clean()));\n") - ; - } -} - -class_alias('Twig_Node_Spaceless', 'Twig\Node\SpacelessNode', false); diff --git a/system/libs/Twig/Node/SpacelessNode.php b/system/libs/Twig/Node/SpacelessNode.php new file mode 100644 index 00000000..c8d32daf --- /dev/null +++ b/system/libs/Twig/Node/SpacelessNode.php @@ -0,0 +1,47 @@ + + */ +class SpacelessNode extends Node +{ + public function __construct(\Twig_NodeInterface $body, $lineno, $tag = 'spaceless') + { + parent::__construct(['body' => $body], [], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ; + if ($compiler->getEnvironment()->isDebug()) { + $compiler->write("ob_start();\n"); + } else { + $compiler->write("ob_start(function () { return ''; });\n"); + } + $compiler + ->subcompile($this->getNode('body')) + ->write("echo trim(preg_replace('/>\s+<', ob_get_clean()));\n") + ; + } +} + +class_alias('Twig\Node\SpacelessNode', 'Twig_Node_Spaceless'); diff --git a/system/libs/Twig/Node/Text.php b/system/libs/Twig/Node/TextNode.php old mode 100755 new mode 100644 similarity index 67% rename from system/libs/Twig/Node/Text.php rename to system/libs/Twig/Node/TextNode.php index f4577fee..9ac435e9 --- a/system/libs/Twig/Node/Text.php +++ b/system/libs/Twig/Node/TextNode.php @@ -10,19 +10,23 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; + /** * Represents a text node. * * @author Fabien Potencier */ -class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface +class TextNode extends Node implements NodeOutputInterface { public function __construct($data, $lineno) { - parent::__construct(array(), array('data' => $data), $lineno); + parent::__construct([], ['data' => $data], $lineno); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->addDebugInfo($this) @@ -33,4 +37,4 @@ class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface } } -class_alias('Twig_Node_Text', 'Twig\Node\TextNode', false); +class_alias('Twig\Node\TextNode', 'Twig_Node_Text'); diff --git a/system/libs/Twig/Node/With.php b/system/libs/Twig/Node/WithNode.php similarity index 52% rename from system/libs/Twig/Node/With.php rename to system/libs/Twig/Node/WithNode.php index 2ab0ea5d..f5ae9246 100644 --- a/system/libs/Twig/Node/With.php +++ b/system/libs/Twig/Node/WithNode.php @@ -9,47 +9,55 @@ * file that was distributed with this source code. */ +namespace Twig\Node; + +use Twig\Compiler; + /** * Represents a nested "with" scope. * * @author Fabien Potencier */ -class Twig_Node_With extends Twig_Node +class WithNode extends Node { - public function __construct(Twig_Node $body, Twig_Node $variables = null, $only = false, $lineno, $tag = null) + public function __construct(Node $body, Node $variables = null, $only = false, $lineno, $tag = null) { - $nodes = array('body' => $body); + $nodes = ['body' => $body]; if (null !== $variables) { $nodes['variables'] = $variables; } - parent::__construct($nodes, array('only' => (bool) $only), $lineno, $tag); + parent::__construct($nodes, ['only' => (bool) $only], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler->addDebugInfo($this); if ($this->hasNode('variables')) { + $node = $this->getNode('variables'); $varsName = $compiler->getVarName(); $compiler ->write(sprintf('$%s = ', $varsName)) - ->subcompile($this->getNode('variables')) + ->subcompile($node) ->raw(";\n") - ->write(sprintf("if (!is_array(\$%s)) {\n", $varsName)) + ->write(sprintf("if (!twig_test_iterable(\$%s)) {\n", $varsName)) ->indent() - ->write("throw new Twig_Error_Runtime('Variables passed to the \"with\" tag must be a hash.');\n") + ->write("throw new RuntimeError('Variables passed to the \"with\" tag must be a hash.', ") + ->repr($node->getTemplateLine()) + ->raw(", \$this->getSourceContext());\n") ->outdent() ->write("}\n") + ->write(sprintf("\$%s = twig_to_array(\$%s);\n", $varsName, $varsName)) ; if ($this->getAttribute('only')) { - $compiler->write("\$context = array('_parent' => \$context);\n"); + $compiler->write("\$context = ['_parent' => \$context];\n"); } else { $compiler->write("\$context['_parent'] = \$context;\n"); } - $compiler->write(sprintf("\$context = array_merge(\$context, \$%s);\n", $varsName)); + $compiler->write(sprintf("\$context = \$this->env->mergeGlobals(array_merge(\$context, \$%s));\n", $varsName)); } else { $compiler->write("\$context['_parent'] = \$context;\n"); } @@ -61,4 +69,4 @@ class Twig_Node_With extends Twig_Node } } -class_alias('Twig_Node_With', 'Twig\Node\WithNode', false); +class_alias('Twig\Node\WithNode', 'Twig_Node_With'); diff --git a/system/libs/Twig/NodeTraverser.php b/system/libs/Twig/NodeTraverser.php index 787629ce..bd25d3cc 100755 --- a/system/libs/Twig/NodeTraverser.php +++ b/system/libs/Twig/NodeTraverser.php @@ -9,8 +9,12 @@ * file that was distributed with this source code. */ +namespace Twig; + +use Twig\NodeVisitor\NodeVisitorInterface; + /** - * Twig_NodeTraverser is a node traverser. + * A node traverser. * * It visits all nodes and their children and calls the given visitor for each. * @@ -18,16 +22,15 @@ * * @author Fabien Potencier */ -class Twig_NodeTraverser +class NodeTraverser { protected $env; - protected $visitors = array(); + protected $visitors = []; /** - * @param Twig_Environment $env - * @param Twig_NodeVisitorInterface[] $visitors + * @param NodeVisitorInterface[] $visitors */ - public function __construct(Twig_Environment $env, array $visitors = array()) + public function __construct(Environment $env, array $visitors = []) { $this->env = $env; foreach ($visitors as $visitor) { @@ -35,21 +38,17 @@ class Twig_NodeTraverser } } - public function addVisitor(Twig_NodeVisitorInterface $visitor) + public function addVisitor(NodeVisitorInterface $visitor) { - if (!isset($this->visitors[$visitor->getPriority()])) { - $this->visitors[$visitor->getPriority()] = array(); - } - $this->visitors[$visitor->getPriority()][] = $visitor; } /** * Traverses a node and calls the registered visitors. * - * @return Twig_NodeInterface + * @return \Twig_NodeInterface */ - public function traverse(Twig_NodeInterface $node) + public function traverse(\Twig_NodeInterface $node) { ksort($this->visitors); foreach ($this->visitors as $visitors) { @@ -61,7 +60,7 @@ class Twig_NodeTraverser return $node; } - protected function traverseForVisitor(Twig_NodeVisitorInterface $visitor, Twig_NodeInterface $node = null) + protected function traverseForVisitor(NodeVisitorInterface $visitor, \Twig_NodeInterface $node = null) { if (null === $node) { return; @@ -70,8 +69,14 @@ class Twig_NodeTraverser $node = $visitor->enterNode($node, $this->env); foreach ($node as $k => $n) { - if (false !== $n = $this->traverseForVisitor($visitor, $n)) { - $node->setNode($k, $n); + if (null === $n) { + continue; + } + + if (false !== ($m = $this->traverseForVisitor($visitor, $n)) && null !== $m) { + if ($m !== $n) { + $node->setNode($k, $m); + } } else { $node->removeNode($k); } @@ -81,4 +86,4 @@ class Twig_NodeTraverser } } -class_alias('Twig_NodeTraverser', 'Twig\NodeTraverser', false); +class_alias('Twig\NodeTraverser', 'Twig_NodeTraverser'); diff --git a/system/libs/Twig/NodeVisitor/AbstractNodeVisitor.php b/system/libs/Twig/NodeVisitor/AbstractNodeVisitor.php new file mode 100644 index 00000000..b66c3c6f --- /dev/null +++ b/system/libs/Twig/NodeVisitor/AbstractNodeVisitor.php @@ -0,0 +1,59 @@ + + */ +abstract class AbstractNodeVisitor implements NodeVisitorInterface +{ + final public function enterNode(\Twig_NodeInterface $node, Environment $env) + { + if (!$node instanceof Node) { + throw new \LogicException(sprintf('%s only supports \Twig\Node\Node instances.', __CLASS__)); + } + + return $this->doEnterNode($node, $env); + } + + final public function leaveNode(\Twig_NodeInterface $node, Environment $env) + { + if (!$node instanceof Node) { + throw new \LogicException(sprintf('%s only supports \Twig\Node\Node instances.', __CLASS__)); + } + + return $this->doLeaveNode($node, $env); + } + + /** + * Called before child nodes are visited. + * + * @return Node The modified node + */ + abstract protected function doEnterNode(Node $node, Environment $env); + + /** + * Called after child nodes are visited. + * + * @return Node|false|null The modified node or null if the node must be removed + */ + abstract protected function doLeaveNode(Node $node, Environment $env); +} + +class_alias('Twig\NodeVisitor\AbstractNodeVisitor', 'Twig_BaseNodeVisitor'); diff --git a/system/libs/Twig/NodeVisitor/Escaper.php b/system/libs/Twig/NodeVisitor/Escaper.php deleted file mode 100755 index 1a1ae66f..00000000 --- a/system/libs/Twig/NodeVisitor/Escaper.php +++ /dev/null @@ -1,154 +0,0 @@ - - */ -class Twig_NodeVisitor_Escaper extends Twig_BaseNodeVisitor -{ - protected $statusStack = array(); - protected $blocks = array(); - protected $safeAnalysis; - protected $traverser; - protected $defaultStrategy = false; - protected $safeVars = array(); - - public function __construct() - { - $this->safeAnalysis = new Twig_NodeVisitor_SafeAnalysis(); - } - - protected function doEnterNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_Module) { - if ($env->hasExtension('Twig_Extension_Escaper') && $defaultStrategy = $env->getExtension('Twig_Extension_Escaper')->getDefaultStrategy($node->getTemplateName())) { - $this->defaultStrategy = $defaultStrategy; - } - $this->safeVars = array(); - $this->blocks = array(); - } elseif ($node instanceof Twig_Node_AutoEscape) { - $this->statusStack[] = $node->getAttribute('value'); - } elseif ($node instanceof Twig_Node_Block) { - $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env); - } elseif ($node instanceof Twig_Node_Import) { - $this->safeVars[] = $node->getNode('var')->getAttribute('name'); - } - - return $node; - } - - protected function doLeaveNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_Module) { - $this->defaultStrategy = false; - $this->safeVars = array(); - $this->blocks = array(); - } elseif ($node instanceof Twig_Node_Expression_Filter) { - return $this->preEscapeFilterNode($node, $env); - } elseif ($node instanceof Twig_Node_Print) { - return $this->escapePrintNode($node, $env, $this->needEscaping($env)); - } - - if ($node instanceof Twig_Node_AutoEscape || $node instanceof Twig_Node_Block) { - array_pop($this->statusStack); - } elseif ($node instanceof Twig_Node_BlockReference) { - $this->blocks[$node->getAttribute('name')] = $this->needEscaping($env); - } - - return $node; - } - - protected function escapePrintNode(Twig_Node_Print $node, Twig_Environment $env, $type) - { - if (false === $type) { - return $node; - } - - $expression = $node->getNode('expr'); - - if ($this->isSafeFor($type, $expression, $env)) { - return $node; - } - - $class = get_class($node); - - return new $class( - $this->getEscaperFilter($type, $expression), - $node->getTemplateLine() - ); - } - - protected function preEscapeFilterNode(Twig_Node_Expression_Filter $filter, Twig_Environment $env) - { - $name = $filter->getNode('filter')->getAttribute('value'); - - $type = $env->getFilter($name)->getPreEscape(); - if (null === $type) { - return $filter; - } - - $node = $filter->getNode('node'); - if ($this->isSafeFor($type, $node, $env)) { - return $filter; - } - - $filter->setNode('node', $this->getEscaperFilter($type, $node)); - - return $filter; - } - - protected function isSafeFor($type, Twig_NodeInterface $expression, $env) - { - $safe = $this->safeAnalysis->getSafe($expression); - - if (null === $safe) { - if (null === $this->traverser) { - $this->traverser = new Twig_NodeTraverser($env, array($this->safeAnalysis)); - } - - $this->safeAnalysis->setSafeVars($this->safeVars); - - $this->traverser->traverse($expression); - $safe = $this->safeAnalysis->getSafe($expression); - } - - return in_array($type, $safe) || in_array('all', $safe); - } - - protected function needEscaping(Twig_Environment $env) - { - if (count($this->statusStack)) { - return $this->statusStack[count($this->statusStack) - 1]; - } - - return $this->defaultStrategy ? $this->defaultStrategy : false; - } - - protected function getEscaperFilter($type, Twig_NodeInterface $node) - { - $line = $node->getTemplateLine(); - $name = new Twig_Node_Expression_Constant('escape', $line); - $args = new Twig_Node(array(new Twig_Node_Expression_Constant((string) $type, $line), new Twig_Node_Expression_Constant(null, $line), new Twig_Node_Expression_Constant(true, $line))); - - return new Twig_Node_Expression_Filter($node, $name, $args, $line); - } - - public function getPriority() - { - return 0; - } -} - -class_alias('Twig_NodeVisitor_Escaper', 'Twig\NodeVisitor\EscaperNodeVisitor', false); diff --git a/system/libs/Twig/NodeVisitor/EscaperNodeVisitor.php b/system/libs/Twig/NodeVisitor/EscaperNodeVisitor.php new file mode 100644 index 00000000..f6e16fa7 --- /dev/null +++ b/system/libs/Twig/NodeVisitor/EscaperNodeVisitor.php @@ -0,0 +1,209 @@ + + */ +class EscaperNodeVisitor extends AbstractNodeVisitor +{ + protected $statusStack = []; + protected $blocks = []; + protected $safeAnalysis; + protected $traverser; + protected $defaultStrategy = false; + protected $safeVars = []; + + public function __construct() + { + $this->safeAnalysis = new SafeAnalysisNodeVisitor(); + } + + protected function doEnterNode(Node $node, Environment $env) + { + if ($node instanceof ModuleNode) { + if ($env->hasExtension('\Twig\Extension\EscaperExtension') && $defaultStrategy = $env->getExtension('\Twig\Extension\EscaperExtension')->getDefaultStrategy($node->getTemplateName())) { + $this->defaultStrategy = $defaultStrategy; + } + $this->safeVars = []; + $this->blocks = []; + } elseif ($node instanceof AutoEscapeNode) { + $this->statusStack[] = $node->getAttribute('value'); + } elseif ($node instanceof BlockNode) { + $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env); + } elseif ($node instanceof ImportNode) { + $this->safeVars[] = $node->getNode('var')->getAttribute('name'); + } + + return $node; + } + + protected function doLeaveNode(Node $node, Environment $env) + { + if ($node instanceof ModuleNode) { + $this->defaultStrategy = false; + $this->safeVars = []; + $this->blocks = []; + } elseif ($node instanceof FilterExpression) { + return $this->preEscapeFilterNode($node, $env); + } elseif ($node instanceof PrintNode && false !== $type = $this->needEscaping($env)) { + $expression = $node->getNode('expr'); + if ($expression instanceof ConditionalExpression && $this->shouldUnwrapConditional($expression, $env, $type)) { + return new DoNode($this->unwrapConditional($expression, $env, $type), $expression->getTemplateLine()); + } + + return $this->escapePrintNode($node, $env, $type); + } + + if ($node instanceof AutoEscapeNode || $node instanceof BlockNode) { + array_pop($this->statusStack); + } elseif ($node instanceof BlockReferenceNode) { + $this->blocks[$node->getAttribute('name')] = $this->needEscaping($env); + } + + return $node; + } + + private function shouldUnwrapConditional(ConditionalExpression $expression, Environment $env, $type) + { + $expr2Safe = $this->isSafeFor($type, $expression->getNode('expr2'), $env); + $expr3Safe = $this->isSafeFor($type, $expression->getNode('expr3'), $env); + + return $expr2Safe !== $expr3Safe; + } + + private function unwrapConditional(ConditionalExpression $expression, Environment $env, $type) + { + // convert "echo a ? b : c" to "a ? echo b : echo c" recursively + $expr2 = $expression->getNode('expr2'); + if ($expr2 instanceof ConditionalExpression && $this->shouldUnwrapConditional($expr2, $env, $type)) { + $expr2 = $this->unwrapConditional($expr2, $env, $type); + } else { + $expr2 = $this->escapeInlinePrintNode(new InlinePrint($expr2, $expr2->getTemplateLine()), $env, $type); + } + $expr3 = $expression->getNode('expr3'); + if ($expr3 instanceof ConditionalExpression && $this->shouldUnwrapConditional($expr3, $env, $type)) { + $expr3 = $this->unwrapConditional($expr3, $env, $type); + } else { + $expr3 = $this->escapeInlinePrintNode(new InlinePrint($expr3, $expr3->getTemplateLine()), $env, $type); + } + + return new ConditionalExpression($expression->getNode('expr1'), $expr2, $expr3, $expression->getTemplateLine()); + } + + private function escapeInlinePrintNode(InlinePrint $node, Environment $env, $type) + { + $expression = $node->getNode('node'); + + if ($this->isSafeFor($type, $expression, $env)) { + return $node; + } + + return new InlinePrint($this->getEscaperFilter($type, $expression), $node->getTemplateLine()); + } + + protected function escapePrintNode(PrintNode $node, Environment $env, $type) + { + if (false === $type) { + return $node; + } + + $expression = $node->getNode('expr'); + + if ($this->isSafeFor($type, $expression, $env)) { + return $node; + } + + $class = \get_class($node); + + return new $class($this->getEscaperFilter($type, $expression), $node->getTemplateLine()); + } + + protected function preEscapeFilterNode(FilterExpression $filter, Environment $env) + { + $name = $filter->getNode('filter')->getAttribute('value'); + + $type = $env->getFilter($name)->getPreEscape(); + if (null === $type) { + return $filter; + } + + $node = $filter->getNode('node'); + if ($this->isSafeFor($type, $node, $env)) { + return $filter; + } + + $filter->setNode('node', $this->getEscaperFilter($type, $node)); + + return $filter; + } + + protected function isSafeFor($type, \Twig_NodeInterface $expression, $env) + { + $safe = $this->safeAnalysis->getSafe($expression); + + if (null === $safe) { + if (null === $this->traverser) { + $this->traverser = new NodeTraverser($env, [$this->safeAnalysis]); + } + + $this->safeAnalysis->setSafeVars($this->safeVars); + + $this->traverser->traverse($expression); + $safe = $this->safeAnalysis->getSafe($expression); + } + + return \in_array($type, $safe) || \in_array('all', $safe); + } + + protected function needEscaping(Environment $env) + { + if (\count($this->statusStack)) { + return $this->statusStack[\count($this->statusStack) - 1]; + } + + return $this->defaultStrategy ? $this->defaultStrategy : false; + } + + protected function getEscaperFilter($type, \Twig_NodeInterface $node) + { + $line = $node->getTemplateLine(); + $name = new ConstantExpression('escape', $line); + $args = new Node([new ConstantExpression((string) $type, $line), new ConstantExpression(null, $line), new ConstantExpression(true, $line)]); + + return new FilterExpression($node, $name, $args, $line); + } + + public function getPriority() + { + return 0; + } +} + +class_alias('Twig\NodeVisitor\EscaperNodeVisitor', 'Twig_NodeVisitor_Escaper'); diff --git a/system/libs/Twig/NodeVisitor/NodeVisitorInterface.php b/system/libs/Twig/NodeVisitor/NodeVisitorInterface.php new file mode 100644 index 00000000..9b8730b4 --- /dev/null +++ b/system/libs/Twig/NodeVisitor/NodeVisitorInterface.php @@ -0,0 +1,50 @@ + + */ +interface NodeVisitorInterface +{ + /** + * Called before child nodes are visited. + * + * @return \Twig_NodeInterface The modified node + */ + public function enterNode(\Twig_NodeInterface $node, Environment $env); + + /** + * Called after child nodes are visited. + * + * @return \Twig_NodeInterface|false|null The modified node or null if the node must be removed + */ + public function leaveNode(\Twig_NodeInterface $node, Environment $env); + + /** + * Returns the priority for this visitor. + * + * Priority should be between -10 and 10 (0 is the default). + * + * @return int The priority level + */ + public function getPriority(); +} + +class_alias('Twig\NodeVisitor\NodeVisitorInterface', 'Twig_NodeVisitorInterface'); + +// Ensure that the aliased name is loaded to keep BC for classes implementing the typehint with the old aliased name. +class_exists('Twig\Environment'); diff --git a/system/libs/Twig/NodeVisitor/Optimizer.php b/system/libs/Twig/NodeVisitor/OptimizerNodeVisitor.php old mode 100755 new mode 100644 similarity index 57% rename from system/libs/Twig/NodeVisitor/Optimizer.php rename to system/libs/Twig/NodeVisitor/OptimizerNodeVisitor.php index 2fa19f3d..e5ea9b7c --- a/system/libs/Twig/NodeVisitor/Optimizer.php +++ b/system/libs/Twig/NodeVisitor/OptimizerNodeVisitor.php @@ -9,8 +9,28 @@ * file that was distributed with this source code. */ +namespace Twig\NodeVisitor; + +use Twig\Environment; +use Twig\Node\BlockReferenceNode; +use Twig\Node\BodyNode; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\BlockReferenceExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FilterExpression; +use Twig\Node\Expression\FunctionExpression; +use Twig\Node\Expression\GetAttrExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Expression\ParentExpression; +use Twig\Node\Expression\TempNameExpression; +use Twig\Node\ForNode; +use Twig\Node\IncludeNode; +use Twig\Node\Node; +use Twig\Node\PrintNode; +use Twig\Node\SetTempNode; + /** - * Twig_NodeVisitor_Optimizer tries to optimizes the AST. + * Tries to optimize the AST. * * This visitor is always the last registered one. * @@ -21,7 +41,7 @@ * * @author Fabien Potencier */ -class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor +class OptimizerNodeVisitor extends AbstractNodeVisitor { const OPTIMIZE_ALL = -1; const OPTIMIZE_NONE = 0; @@ -29,10 +49,10 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor const OPTIMIZE_RAW_FILTER = 4; const OPTIMIZE_VAR_ACCESS = 8; - protected $loops = array(); - protected $loopsTargets = array(); + protected $loops = []; + protected $loopsTargets = []; protected $optimizers; - protected $prependedNodes = array(); + protected $prependedNodes = []; protected $inABody = false; /** @@ -40,29 +60,29 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor */ public function __construct($optimizers = -1) { - if (!is_int($optimizers) || $optimizers > (self::OPTIMIZE_FOR | self::OPTIMIZE_RAW_FILTER | self::OPTIMIZE_VAR_ACCESS)) { - throw new InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers)); + if (!\is_int($optimizers) || $optimizers > (self::OPTIMIZE_FOR | self::OPTIMIZE_RAW_FILTER | self::OPTIMIZE_VAR_ACCESS)) { + throw new \InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers)); } $this->optimizers = $optimizers; } - protected function doEnterNode(Twig_Node $node, Twig_Environment $env) + protected function doEnterNode(Node $node, Environment $env) { if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) { $this->enterOptimizeFor($node, $env); } - if (PHP_VERSION_ID < 50400 && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('Twig_Extension_Sandbox')) { + if (\PHP_VERSION_ID < 50400 && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('\Twig\Extension\SandboxExtension')) { if ($this->inABody) { - if (!$node instanceof Twig_Node_Expression) { - if (get_class($node) !== 'Twig_Node') { - array_unshift($this->prependedNodes, array()); + if (!$node instanceof AbstractExpression) { + if ('Twig_Node' !== \get_class($node)) { + array_unshift($this->prependedNodes, []); } } else { $node = $this->optimizeVariables($node, $env); } - } elseif ($node instanceof Twig_Node_Body) { + } elseif ($node instanceof BodyNode) { $this->inABody = true; } } @@ -70,9 +90,9 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor return $node; } - protected function doLeaveNode(Twig_Node $node, Twig_Environment $env) + protected function doLeaveNode(Node $node, Environment $env) { - $expression = $node instanceof Twig_Node_Expression; + $expression = $node instanceof AbstractExpression; if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) { $this->leaveOptimizeFor($node, $env); @@ -84,18 +104,18 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor $node = $this->optimizePrintNode($node, $env); - if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('Twig_Extension_Sandbox')) { - if ($node instanceof Twig_Node_Body) { + if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('\Twig\Extension\SandboxExtension')) { + if ($node instanceof BodyNode) { $this->inABody = false; } elseif ($this->inABody) { - if (!$expression && get_class($node) !== 'Twig_Node' && $prependedNodes = array_shift($this->prependedNodes)) { - $nodes = array(); + if (!$expression && 'Twig_Node' !== \get_class($node) && $prependedNodes = array_shift($this->prependedNodes)) { + $nodes = []; foreach (array_unique($prependedNodes) as $name) { - $nodes[] = new Twig_Node_SetTemp($name, $node->getTemplateLine()); + $nodes[] = new SetTempNode($name, $node->getTemplateLine()); } $nodes[] = $node; - $node = new Twig_Node($nodes); + $node = new Node($nodes); } } } @@ -103,12 +123,12 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor return $node; } - protected function optimizeVariables(Twig_NodeInterface $node, Twig_Environment $env) + protected function optimizeVariables(\Twig_NodeInterface $node, Environment $env) { - if ('Twig_Node_Expression_Name' === get_class($node) && $node->isSimple()) { + if ('Twig_Node_Expression_Name' === \get_class($node) && $node->isSimple()) { $this->prependedNodes[0][] = $node->getAttribute('name'); - return new Twig_Node_Expression_TempName($node->getAttribute('name'), $node->getTemplateLine()); + return new TempNameExpression($node->getAttribute('name'), $node->getTemplateLine()); } return $node; @@ -121,18 +141,18 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor * * * "echo $this->render(Parent)Block()" with "$this->display(Parent)Block()" * - * @return Twig_NodeInterface + * @return \Twig_NodeInterface */ - protected function optimizePrintNode(Twig_NodeInterface $node, Twig_Environment $env) + protected function optimizePrintNode(\Twig_NodeInterface $node, Environment $env) { - if (!$node instanceof Twig_Node_Print) { + if (!$node instanceof PrintNode) { return $node; } $exprNode = $node->getNode('expr'); if ( - $exprNode instanceof Twig_Node_Expression_BlockReference || - $exprNode instanceof Twig_Node_Expression_Parent + $exprNode instanceof BlockReferenceExpression || + $exprNode instanceof ParentExpression ) { $exprNode->setAttribute('output', true); @@ -145,11 +165,11 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor /** * Removes "raw" filters. * - * @return Twig_NodeInterface + * @return \Twig_NodeInterface */ - protected function optimizeRawFilter(Twig_NodeInterface $node, Twig_Environment $env) + protected function optimizeRawFilter(\Twig_NodeInterface $node, Environment $env) { - if ($node instanceof Twig_Node_Expression_Filter && 'raw' == $node->getNode('filter')->getAttribute('value')) { + if ($node instanceof FilterExpression && 'raw' == $node->getNode('filter')->getAttribute('value')) { return $node->getNode('node'); } @@ -159,9 +179,9 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor /** * Optimizes "for" tag by removing the "loop" variable creation whenever possible. */ - protected function enterOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env) + protected function enterOptimizeFor(\Twig_NodeInterface $node, Environment $env) { - if ($node instanceof Twig_Node_For) { + if ($node instanceof ForNode) { // disable the loop variable by default $node->setAttribute('with_loop', false); array_unshift($this->loops, $node); @@ -175,28 +195,28 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor // when do we need to add the loop variable back? // the loop variable is referenced for the current loop - elseif ($node instanceof Twig_Node_Expression_Name && 'loop' === $node->getAttribute('name')) { + elseif ($node instanceof NameExpression && 'loop' === $node->getAttribute('name')) { $node->setAttribute('always_defined', true); $this->addLoopToCurrent(); } // optimize access to loop targets - elseif ($node instanceof Twig_Node_Expression_Name && in_array($node->getAttribute('name'), $this->loopsTargets)) { + elseif ($node instanceof NameExpression && \in_array($node->getAttribute('name'), $this->loopsTargets)) { $node->setAttribute('always_defined', true); } // block reference - elseif ($node instanceof Twig_Node_BlockReference || $node instanceof Twig_Node_Expression_BlockReference) { + elseif ($node instanceof BlockReferenceNode || $node instanceof BlockReferenceExpression) { $this->addLoopToCurrent(); } // include without the only attribute - elseif ($node instanceof Twig_Node_Include && !$node->getAttribute('only')) { + elseif ($node instanceof IncludeNode && !$node->getAttribute('only')) { $this->addLoopToAll(); } // include function without the with_context=false parameter - elseif ($node instanceof Twig_Node_Expression_Function + elseif ($node instanceof FunctionExpression && 'include' === $node->getAttribute('name') && (!$node->getNode('arguments')->hasNode('with_context') || false !== $node->getNode('arguments')->getNode('with_context')->getAttribute('value') @@ -206,12 +226,12 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor } // the loop variable is referenced via an attribute - elseif ($node instanceof Twig_Node_Expression_GetAttr - && (!$node->getNode('attribute') instanceof Twig_Node_Expression_Constant + elseif ($node instanceof GetAttrExpression + && (!$node->getNode('attribute') instanceof ConstantExpression || 'parent' === $node->getNode('attribute')->getAttribute('value') ) && (true === $this->loops[0]->getAttribute('with_loop') - || ($node->getNode('node') instanceof Twig_Node_Expression_Name + || ($node->getNode('node') instanceof NameExpression && 'loop' === $node->getNode('node')->getAttribute('name') ) ) @@ -223,9 +243,9 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor /** * Optimizes "for" tag by removing the "loop" variable creation whenever possible. */ - protected function leaveOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env) + protected function leaveOptimizeFor(\Twig_NodeInterface $node, Environment $env) { - if ($node instanceof Twig_Node_For) { + if ($node instanceof ForNode) { array_shift($this->loops); array_shift($this->loopsTargets); array_shift($this->loopsTargets); @@ -250,4 +270,4 @@ class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor } } -class_alias('Twig_NodeVisitor_Optimizer', 'Twig\NodeVisitor\OptimizerNodeVisitor', false); +class_alias('Twig\NodeVisitor\OptimizerNodeVisitor', 'Twig_NodeVisitor_Optimizer'); diff --git a/system/libs/Twig/NodeVisitor/SafeAnalysis.php b/system/libs/Twig/NodeVisitor/SafeAnalysisNodeVisitor.php old mode 100755 new mode 100644 similarity index 57% rename from system/libs/Twig/NodeVisitor/SafeAnalysis.php rename to system/libs/Twig/NodeVisitor/SafeAnalysisNodeVisitor.php index ca31c8fc..97a7a3e6 --- a/system/libs/Twig/NodeVisitor/SafeAnalysis.php +++ b/system/libs/Twig/NodeVisitor/SafeAnalysisNodeVisitor.php @@ -9,20 +9,34 @@ * file that was distributed with this source code. */ +namespace Twig\NodeVisitor; + +use Twig\Environment; +use Twig\Node\Expression\BlockReferenceExpression; +use Twig\Node\Expression\ConditionalExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FilterExpression; +use Twig\Node\Expression\FunctionExpression; +use Twig\Node\Expression\GetAttrExpression; +use Twig\Node\Expression\MethodCallExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Expression\ParentExpression; +use Twig\Node\Node; + /** * @final */ -class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor +class SafeAnalysisNodeVisitor extends AbstractNodeVisitor { - protected $data = array(); - protected $safeVars = array(); + protected $data = []; + protected $safeVars = []; public function setSafeVars($safeVars) { $this->safeVars = $safeVars; } - public function getSafe(Twig_NodeInterface $node) + public function getSafe(\Twig_NodeInterface $node) { $hash = spl_object_hash($node); if (!isset($this->data[$hash])) { @@ -34,7 +48,7 @@ class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor continue; } - if (in_array('html_attr', $bucket['value'])) { + if (\in_array('html_attr', $bucket['value'])) { $bucket['value'][] = 'html'; } @@ -42,7 +56,7 @@ class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor } } - protected function setSafe(Twig_NodeInterface $node, array $safe) + protected function setSafe(\Twig_NodeInterface $node, array $safe) { $hash = spl_object_hash($node); if (isset($this->data[$hash])) { @@ -54,33 +68,33 @@ class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor } } } - $this->data[$hash][] = array( + $this->data[$hash][] = [ 'key' => $node, 'value' => $safe, - ); + ]; } - protected function doEnterNode(Twig_Node $node, Twig_Environment $env) + protected function doEnterNode(Node $node, Environment $env) { return $node; } - protected function doLeaveNode(Twig_Node $node, Twig_Environment $env) + protected function doLeaveNode(Node $node, Environment $env) { - if ($node instanceof Twig_Node_Expression_Constant) { + if ($node instanceof ConstantExpression) { // constants are marked safe for all - $this->setSafe($node, array('all')); - } elseif ($node instanceof Twig_Node_Expression_BlockReference) { + $this->setSafe($node, ['all']); + } elseif ($node instanceof BlockReferenceExpression) { // blocks are safe by definition - $this->setSafe($node, array('all')); - } elseif ($node instanceof Twig_Node_Expression_Parent) { + $this->setSafe($node, ['all']); + } elseif ($node instanceof ParentExpression) { // parent block is safe by definition - $this->setSafe($node, array('all')); - } elseif ($node instanceof Twig_Node_Expression_Conditional) { + $this->setSafe($node, ['all']); + } elseif ($node instanceof ConditionalExpression) { // intersect safeness of both operands $safe = $this->intersectSafe($this->getSafe($node->getNode('expr2')), $this->getSafe($node->getNode('expr3'))); $this->setSafe($node, $safe); - } elseif ($node instanceof Twig_Node_Expression_Filter) { + } elseif ($node instanceof FilterExpression) { // filter expression is safe when the filter is safe $name = $node->getNode('filter')->getAttribute('value'); $args = $node->getNode('arguments'); @@ -91,9 +105,9 @@ class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor } $this->setSafe($node, $safe); } else { - $this->setSafe($node, array()); + $this->setSafe($node, []); } - } elseif ($node instanceof Twig_Node_Expression_Function) { + } elseif ($node instanceof FunctionExpression) { // function expression is safe when the function is safe $name = $node->getAttribute('name'); $args = $node->getNode('arguments'); @@ -101,24 +115,24 @@ class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor if (false !== $function) { $this->setSafe($node, $function->getSafe($args)); } else { - $this->setSafe($node, array()); + $this->setSafe($node, []); } - } elseif ($node instanceof Twig_Node_Expression_MethodCall) { + } elseif ($node instanceof MethodCallExpression) { if ($node->getAttribute('safe')) { - $this->setSafe($node, array('all')); + $this->setSafe($node, ['all']); } else { - $this->setSafe($node, array()); + $this->setSafe($node, []); } - } elseif ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name) { + } elseif ($node instanceof GetAttrExpression && $node->getNode('node') instanceof NameExpression) { $name = $node->getNode('node')->getAttribute('name'); // attributes on template instances are safe - if ('_self' == $name || in_array($name, $this->safeVars)) { - $this->setSafe($node, array('all')); + if ('_self' == $name || \in_array($name, $this->safeVars)) { + $this->setSafe($node, ['all']); } else { - $this->setSafe($node, array()); + $this->setSafe($node, []); } } else { - $this->setSafe($node, array()); + $this->setSafe($node, []); } return $node; @@ -127,14 +141,14 @@ class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor protected function intersectSafe(array $a = null, array $b = null) { if (null === $a || null === $b) { - return array(); + return []; } - if (in_array('all', $a)) { + if (\in_array('all', $a)) { return $b; } - if (in_array('all', $b)) { + if (\in_array('all', $b)) { return $a; } @@ -147,4 +161,4 @@ class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor } } -class_alias('Twig_NodeVisitor_SafeAnalysis', 'Twig\NodeVisitor\SafeAnalysisNodeVisitor', false); +class_alias('Twig\NodeVisitor\SafeAnalysisNodeVisitor', 'Twig_NodeVisitor_SafeAnalysis'); diff --git a/system/libs/Twig/NodeVisitor/Sandbox.php b/system/libs/Twig/NodeVisitor/Sandbox.php deleted file mode 100755 index b631b29d..00000000 --- a/system/libs/Twig/NodeVisitor/Sandbox.php +++ /dev/null @@ -1,77 +0,0 @@ - - */ -class Twig_NodeVisitor_Sandbox extends Twig_BaseNodeVisitor -{ - protected $inAModule = false; - protected $tags; - protected $filters; - protected $functions; - - protected function doEnterNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_Module) { - $this->inAModule = true; - $this->tags = array(); - $this->filters = array(); - $this->functions = array(); - - return $node; - } elseif ($this->inAModule) { - // look for tags - if ($node->getNodeTag() && !isset($this->tags[$node->getNodeTag()])) { - $this->tags[$node->getNodeTag()] = $node; - } - - // look for filters - if ($node instanceof Twig_Node_Expression_Filter && !isset($this->filters[$node->getNode('filter')->getAttribute('value')])) { - $this->filters[$node->getNode('filter')->getAttribute('value')] = $node; - } - - // look for functions - if ($node instanceof Twig_Node_Expression_Function && !isset($this->functions[$node->getAttribute('name')])) { - $this->functions[$node->getAttribute('name')] = $node; - } - - // wrap print to check __toString() calls - if ($node instanceof Twig_Node_Print) { - return new Twig_Node_SandboxedPrint($node->getNode('expr'), $node->getTemplateLine(), $node->getNodeTag()); - } - } - - return $node; - } - - protected function doLeaveNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_Module) { - $this->inAModule = false; - - $node->setNode('display_start', new Twig_Node(array(new Twig_Node_CheckSecurity($this->filters, $this->tags, $this->functions), $node->getNode('display_start')))); - } - - return $node; - } - - public function getPriority() - { - return 0; - } -} - -class_alias('Twig_NodeVisitor_Sandbox', 'Twig\NodeVisitor\SandboxNodeVisitor', false); diff --git a/system/libs/Twig/NodeVisitor/SandboxNodeVisitor.php b/system/libs/Twig/NodeVisitor/SandboxNodeVisitor.php new file mode 100644 index 00000000..c9403398 --- /dev/null +++ b/system/libs/Twig/NodeVisitor/SandboxNodeVisitor.php @@ -0,0 +1,137 @@ + + */ +class SandboxNodeVisitor extends AbstractNodeVisitor +{ + protected $inAModule = false; + protected $tags; + protected $filters; + protected $functions; + + private $needsToStringWrap = false; + + protected function doEnterNode(Node $node, Environment $env) + { + if ($node instanceof ModuleNode) { + $this->inAModule = true; + $this->tags = []; + $this->filters = []; + $this->functions = []; + + return $node; + } elseif ($this->inAModule) { + // look for tags + if ($node->getNodeTag() && !isset($this->tags[$node->getNodeTag()])) { + $this->tags[$node->getNodeTag()] = $node; + } + + // look for filters + if ($node instanceof FilterExpression && !isset($this->filters[$node->getNode('filter')->getAttribute('value')])) { + $this->filters[$node->getNode('filter')->getAttribute('value')] = $node; + } + + // look for functions + if ($node instanceof FunctionExpression && !isset($this->functions[$node->getAttribute('name')])) { + $this->functions[$node->getAttribute('name')] = $node; + } + + // the .. operator is equivalent to the range() function + if ($node instanceof RangeBinary && !isset($this->functions['range'])) { + $this->functions['range'] = $node; + } + + if ($node instanceof PrintNode) { + $this->needsToStringWrap = true; + $this->wrapNode($node, 'expr'); + } + + if ($node instanceof SetNode && !$node->getAttribute('capture')) { + $this->needsToStringWrap = true; + } + + // wrap outer nodes that can implicitly call __toString() + if ($this->needsToStringWrap) { + if ($node instanceof ConcatBinary) { + $this->wrapNode($node, 'left'); + $this->wrapNode($node, 'right'); + } + if ($node instanceof FilterExpression) { + $this->wrapNode($node, 'node'); + $this->wrapArrayNode($node, 'arguments'); + } + if ($node instanceof FunctionExpression) { + $this->wrapArrayNode($node, 'arguments'); + } + } + } + + return $node; + } + + protected function doLeaveNode(Node $node, Environment $env) + { + if ($node instanceof ModuleNode) { + $this->inAModule = false; + + $node->getNode('constructor_end')->setNode('_security_check', new Node([new CheckSecurityNode($this->filters, $this->tags, $this->functions), $node->getNode('display_start')])); + } elseif ($this->inAModule) { + if ($node instanceof PrintNode || $node instanceof SetNode) { + $this->needsToStringWrap = false; + } + } + + return $node; + } + + private function wrapNode(Node $node, $name) + { + $expr = $node->getNode($name); + if ($expr instanceof NameExpression || $expr instanceof GetAttrExpression) { + $node->setNode($name, new CheckToStringNode($expr)); + } + } + + private function wrapArrayNode(Node $node, $name) + { + $args = $node->getNode($name); + foreach ($args as $name => $_) { + $this->wrapNode($args, $name); + } + } + + public function getPriority() + { + return 0; + } +} + +class_alias('Twig\NodeVisitor\SandboxNodeVisitor', 'Twig_NodeVisitor_Sandbox'); diff --git a/system/libs/Twig/NodeVisitorInterface.php b/system/libs/Twig/NodeVisitorInterface.php deleted file mode 100755 index 1270a372..00000000 --- a/system/libs/Twig/NodeVisitorInterface.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ -interface Twig_NodeVisitorInterface -{ - /** - * Called before child nodes are visited. - * - * @return Twig_NodeInterface The modified node - */ - public function enterNode(Twig_NodeInterface $node, Twig_Environment $env); - - /** - * Called after child nodes are visited. - * - * @return Twig_NodeInterface|false The modified node or false if the node must be removed - */ - public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env); - - /** - * Returns the priority for this visitor. - * - * Priority should be between -10 and 10 (0 is the default). - * - * @return int The priority level - */ - public function getPriority(); -} - -class_alias('Twig_NodeVisitorInterface', 'Twig\NodeVisitor\NodeVisitorInterface', false); -class_exists('Twig_Environment'); -class_exists('Twig_Node'); diff --git a/system/libs/Twig/Parser.php b/system/libs/Twig/Parser.php index e796f197..0ea102cc 100755 --- a/system/libs/Twig/Parser.php +++ b/system/libs/Twig/Parser.php @@ -10,14 +10,31 @@ * file that was distributed with this source code. */ +namespace Twig; + +use Twig\Error\SyntaxError; +use Twig\Node\BlockNode; +use Twig\Node\BlockReferenceNode; +use Twig\Node\BodyNode; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\MacroNode; +use Twig\Node\ModuleNode; +use Twig\Node\Node; +use Twig\Node\NodeCaptureInterface; +use Twig\Node\NodeOutputInterface; +use Twig\Node\PrintNode; +use Twig\Node\TextNode; +use Twig\NodeVisitor\NodeVisitorInterface; +use Twig\TokenParser\TokenParserInterface; + /** * Default parser implementation. * * @author Fabien Potencier */ -class Twig_Parser implements Twig_ParserInterface +class Parser implements \Twig_ParserInterface { - protected $stack = array(); + protected $stack = []; protected $stream; protected $parent; protected $handlers; @@ -30,9 +47,10 @@ class Twig_Parser implements Twig_ParserInterface protected $reservedMacroNames; protected $importedSymbols; protected $traits; - protected $embeddedTemplates = array(); + protected $embeddedTemplates = []; + private $varNameSalt = 0; - public function __construct(Twig_Environment $env) + public function __construct(Environment $env) { $this->env = $env; } @@ -49,7 +67,7 @@ class Twig_Parser implements Twig_ParserInterface public function getVarName() { - return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false)); + return sprintf('__internal_%s', hash('sha256', __METHOD__.$this->stream->getSourceContext()->getCode().$this->varNameSalt++)); } /** @@ -62,12 +80,12 @@ class Twig_Parser implements Twig_ParserInterface return $this->stream->getSourceContext()->getName(); } - public function parse(Twig_TokenStream $stream, $test = null, $dropNeedle = false) + public function parse(TokenStream $stream, $test = null, $dropNeedle = false) { // push all variables into the stack to keep the current state of the parser // using get_object_vars() instead of foreach would lead to https://bugs.php.net/71336 // This hack can be removed when min version if PHP 7.0 - $vars = array(); + $vars = []; foreach ($this as $k => $v) { $vars[$k] = $v; } @@ -87,25 +105,26 @@ class Twig_Parser implements Twig_ParserInterface } if (null === $this->expressionParser) { - $this->expressionParser = new Twig_ExpressionParser($this, $this->env); + $this->expressionParser = new ExpressionParser($this, $this->env); } $this->stream = $stream; $this->parent = null; - $this->blocks = array(); - $this->macros = array(); - $this->traits = array(); - $this->blockStack = array(); - $this->importedSymbols = array(array()); - $this->embeddedTemplates = array(); + $this->blocks = []; + $this->macros = []; + $this->traits = []; + $this->blockStack = []; + $this->importedSymbols = [[]]; + $this->embeddedTemplates = []; + $this->varNameSalt = 0; try { $body = $this->subparse($test, $dropNeedle); if (null !== $this->parent && null === $body = $this->filterBodyNodes($body)) { - $body = new Twig_Node(); + $body = new Node(); } - } catch (Twig_Error_Syntax $e) { + } catch (SyntaxError $e) { if (!$e->getSourceContext()) { $e->setSourceContext($this->stream->getSourceContext()); } @@ -117,9 +136,9 @@ class Twig_Parser implements Twig_ParserInterface throw $e; } - $node = new Twig_Node_Module(new Twig_Node_Body(array($body)), $this->parent, new Twig_Node($this->blocks), new Twig_Node($this->macros), new Twig_Node($this->traits), $this->embeddedTemplates, $stream->getSourceContext()); + $node = new ModuleNode(new BodyNode([$body]), $this->parent, new Node($this->blocks), new Node($this->macros), new Node($this->traits), $this->embeddedTemplates, $stream->getSourceContext()); - $traverser = new Twig_NodeTraverser($this->env, $this->visitors); + $traverser = new NodeTraverser($this->env, $this->visitors); $node = $traverser->traverse($node); @@ -134,51 +153,51 @@ class Twig_Parser implements Twig_ParserInterface public function subparse($test, $dropNeedle = false) { $lineno = $this->getCurrentToken()->getLine(); - $rv = array(); + $rv = []; while (!$this->stream->isEOF()) { switch ($this->getCurrentToken()->getType()) { - case Twig_Token::TEXT_TYPE: + case Token::TEXT_TYPE: $token = $this->stream->next(); - $rv[] = new Twig_Node_Text($token->getValue(), $token->getLine()); + $rv[] = new TextNode($token->getValue(), $token->getLine()); break; - case Twig_Token::VAR_START_TYPE: + case Token::VAR_START_TYPE: $token = $this->stream->next(); $expr = $this->expressionParser->parseExpression(); - $this->stream->expect(Twig_Token::VAR_END_TYPE); - $rv[] = new Twig_Node_Print($expr, $token->getLine()); + $this->stream->expect(Token::VAR_END_TYPE); + $rv[] = new PrintNode($expr, $token->getLine()); break; - case Twig_Token::BLOCK_START_TYPE: + case Token::BLOCK_START_TYPE: $this->stream->next(); $token = $this->getCurrentToken(); - if ($token->getType() !== Twig_Token::NAME_TYPE) { - throw new Twig_Error_Syntax('A block must start with a tag name.', $token->getLine(), $this->stream->getSourceContext()); + if (Token::NAME_TYPE !== $token->getType()) { + throw new SyntaxError('A block must start with a tag name.', $token->getLine(), $this->stream->getSourceContext()); } - if (null !== $test && call_user_func($test, $token)) { + if (null !== $test && \call_user_func($test, $token)) { if ($dropNeedle) { $this->stream->next(); } - if (1 === count($rv)) { + if (1 === \count($rv)) { return $rv[0]; } - return new Twig_Node($rv, array(), $lineno); + return new Node($rv, [], $lineno); } $subparser = $this->handlers->getTokenParser($token->getValue()); if (null === $subparser) { if (null !== $test) { - $e = new Twig_Error_Syntax(sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()); + $e = new SyntaxError(sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()); - if (is_array($test) && isset($test[0]) && $test[0] instanceof Twig_TokenParserInterface) { + if (\is_array($test) && isset($test[0]) && $test[0] instanceof TokenParserInterface) { $e->appendMessage(sprintf(' (expecting closing tag for the "%s" tag defined near line %s).', $test[0]->getTag(), $lineno)); } } else { - $e = new Twig_Error_Syntax(sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()); + $e = new SyntaxError(sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()); $e->addSuggestions($token->getValue(), array_keys($this->env->getTags())); } @@ -194,15 +213,15 @@ class Twig_Parser implements Twig_ParserInterface break; default: - throw new Twig_Error_Syntax('Lexer or parser ended up in unsupported state.', $this->getCurrentToken()->getLine(), $this->stream->getSourceContext()); + throw new SyntaxError('Lexer or parser ended up in unsupported state.', $this->getCurrentToken()->getLine(), $this->stream->getSourceContext()); } } - if (1 === count($rv)) { + if (1 === \count($rv)) { return $rv[0]; } - return new Twig_Node($rv, array(), $lineno); + return new Node($rv, [], $lineno); } /** @@ -218,7 +237,7 @@ class Twig_Parser implements Twig_ParserInterface /** * @deprecated since 1.27 (to be removed in 2.0) */ - public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) + public function addNodeVisitor(NodeVisitorInterface $visitor) { @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0.', E_USER_DEPRECATED); @@ -232,7 +251,7 @@ class Twig_Parser implements Twig_ParserInterface public function peekBlockStack() { - return $this->blockStack[count($this->blockStack) - 1]; + return isset($this->blockStack[\count($this->blockStack) - 1]) ? $this->blockStack[\count($this->blockStack) - 1] : null; } public function popBlockStack() @@ -255,9 +274,9 @@ class Twig_Parser implements Twig_ParserInterface return $this->blocks[$name]; } - public function setBlock($name, Twig_Node_Block $value) + public function setBlock($name, BlockNode $value) { - $this->blocks[$name] = new Twig_Node_Body(array($value), array(), $value->getTemplateLine()); + $this->blocks[$name] = new BodyNode([$value], [], $value->getTemplateLine()); } public function hasMacro($name) @@ -265,10 +284,10 @@ class Twig_Parser implements Twig_ParserInterface return isset($this->macros[$name]); } - public function setMacro($name, Twig_Node_Macro $node) + public function setMacro($name, MacroNode $node) { if ($this->isReservedMacroName($name)) { - throw new Twig_Error_Syntax(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword.', $name), $node->getTemplateLine(), $this->stream->getSourceContext()); + throw new SyntaxError(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword.', $name), $node->getTemplateLine(), $this->stream->getSourceContext()); } $this->macros[$name] = $node; @@ -277,8 +296,8 @@ class Twig_Parser implements Twig_ParserInterface public function isReservedMacroName($name) { if (null === $this->reservedMacroNames) { - $this->reservedMacroNames = array(); - $r = new ReflectionClass($this->env->getBaseTemplateClass()); + $this->reservedMacroNames = []; + $r = new \ReflectionClass($this->env->getBaseTemplateClass()); foreach ($r->getMethods() as $method) { $methodName = strtolower($method->getName()); @@ -288,7 +307,7 @@ class Twig_Parser implements Twig_ParserInterface } } - return in_array(strtolower($name), $this->reservedMacroNames); + return \in_array(strtolower($name), $this->reservedMacroNames); } public function addTrait($trait) @@ -298,38 +317,46 @@ class Twig_Parser implements Twig_ParserInterface public function hasTraits() { - return count($this->traits) > 0; + return \count($this->traits) > 0; } - public function embedTemplate(Twig_Node_Module $template) + public function embedTemplate(ModuleNode $template) { $template->setIndex(mt_rand()); $this->embeddedTemplates[] = $template; } - public function addImportedSymbol($type, $alias, $name = null, Twig_Node_Expression $node = null) + public function addImportedSymbol($type, $alias, $name = null, AbstractExpression $node = null) { - $this->importedSymbols[0][$type][$alias] = array('name' => $name, 'node' => $node); + $this->importedSymbols[0][$type][$alias] = ['name' => $name, 'node' => $node]; } public function getImportedSymbol($type, $alias) { - foreach ($this->importedSymbols as $functions) { - if (isset($functions[$type][$alias])) { - return $functions[$type][$alias]; + if (null !== $this->peekBlockStack()) { + foreach ($this->importedSymbols as $functions) { + if (isset($functions[$type][$alias])) { + if (\count($this->blockStack) > 1) { + return null; + } + + return $functions[$type][$alias]; + } } + } else { + return isset($this->importedSymbols[0][$type][$alias]) ? $this->importedSymbols[0][$type][$alias] : null; } } public function isMainScope() { - return 1 === count($this->importedSymbols); + return 1 === \count($this->importedSymbols); } public function pushLocalScope() { - array_unshift($this->importedSymbols, array()); + array_unshift($this->importedSymbols, []); } public function popLocalScope() @@ -338,7 +365,7 @@ class Twig_Parser implements Twig_ParserInterface } /** - * @return Twig_ExpressionParser + * @return ExpressionParser */ public function getExpressionParser() { @@ -356,7 +383,7 @@ class Twig_Parser implements Twig_ParserInterface } /** - * @return Twig_TokenStream + * @return TokenStream */ public function getStream() { @@ -364,34 +391,38 @@ class Twig_Parser implements Twig_ParserInterface } /** - * @return Twig_Token + * @return Token */ public function getCurrentToken() { return $this->stream->getCurrent(); } - protected function filterBodyNodes(Twig_NodeInterface $node) + protected function filterBodyNodes(\Twig_NodeInterface $node) { // check that the body does not contain non-empty output nodes if ( - ($node instanceof Twig_Node_Text && !ctype_space($node->getAttribute('data'))) + ($node instanceof TextNode && !ctype_space($node->getAttribute('data'))) || - (!$node instanceof Twig_Node_Text && !$node instanceof Twig_Node_BlockReference && $node instanceof Twig_NodeOutputInterface) + (!$node instanceof TextNode && !$node instanceof BlockReferenceNode && $node instanceof NodeOutputInterface) ) { - if (false !== strpos((string) $node, chr(0xEF).chr(0xBB).chr(0xBF))) { - throw new Twig_Error_Syntax('A template that extends another one cannot start with a byte order mark (BOM); it must be removed.', $node->getTemplateLine(), $this->stream->getSourceContext()); + if (false !== strpos((string) $node, \chr(0xEF).\chr(0xBB).\chr(0xBF))) { + $t = substr($node->getAttribute('data'), 3); + if ('' === $t || ctype_space($t)) { + // bypass empty nodes starting with a BOM + return; + } } - throw new Twig_Error_Syntax('A template that extends another one cannot include contents outside Twig blocks. Did you forget to put the contents inside a {% block %} tag?', $node->getTemplateLine(), $this->stream->getSourceContext()); + 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()); } // bypass nodes that will "capture" the output - if ($node instanceof Twig_NodeCaptureInterface) { + if ($node instanceof NodeCaptureInterface) { return $node; } - if ($node instanceof Twig_NodeOutputInterface) { + if ($node instanceof NodeOutputInterface) { return; } @@ -405,6 +436,4 @@ class Twig_Parser implements Twig_ParserInterface } } -class_alias('Twig_Parser', 'Twig\Parser', false); -class_exists('Twig_Node'); -class_exists('Twig_TokenStream'); +class_alias('Twig\Parser', 'Twig_Parser'); diff --git a/system/libs/Twig/Profiler/Dumper/Base.php b/system/libs/Twig/Profiler/Dumper/BaseDumper.php similarity index 65% rename from system/libs/Twig/Profiler/Dumper/Base.php rename to system/libs/Twig/Profiler/Dumper/BaseDumper.php index 913afd4f..d965dc75 100644 --- a/system/libs/Twig/Profiler/Dumper/Base.php +++ b/system/libs/Twig/Profiler/Dumper/BaseDumper.php @@ -9,25 +9,29 @@ * file that was distributed with this source code. */ +namespace Twig\Profiler\Dumper; + +use Twig\Profiler\Profile; + /** * @author Fabien Potencier */ -abstract class Twig_Profiler_Dumper_Base +abstract class BaseDumper { private $root; - public function dump(Twig_Profiler_Profile $profile) + public function dump(Profile $profile) { return $this->dumpProfile($profile); } - abstract protected function formatTemplate(Twig_Profiler_Profile $profile, $prefix); + abstract protected function formatTemplate(Profile $profile, $prefix); - abstract protected function formatNonTemplate(Twig_Profiler_Profile $profile, $prefix); + abstract protected function formatNonTemplate(Profile $profile, $prefix); - abstract protected function formatTime(Twig_Profiler_Profile $profile, $percent); + abstract protected function formatTime(Profile $profile, $percent); - private function dumpProfile(Twig_Profiler_Profile $profile, $prefix = '', $sibling = false) + private function dumpProfile(Profile $profile, $prefix = '', $sibling = false) { if ($profile->isRoot()) { $this->root = $profile->getDuration(); @@ -49,7 +53,7 @@ abstract class Twig_Profiler_Dumper_Base $str = sprintf("%s %s\n", $start, $this->formatTime($profile, $percent)); } - $nCount = count($profile->getProfiles()); + $nCount = \count($profile->getProfiles()); foreach ($profile as $i => $p) { $str .= $this->dumpProfile($p, $prefix, $i + 1 !== $nCount); } @@ -58,5 +62,4 @@ abstract class Twig_Profiler_Dumper_Base } } -class_alias('Twig_Profiler_Dumper_Base', 'Twig\Profiler\Dumper\BaseDumper', false); -class_exists('Twig_Profiler_Profile'); +class_alias('Twig\Profiler\Dumper\BaseDumper', 'Twig_Profiler_Dumper_Base'); diff --git a/system/libs/Twig/Profiler/Dumper/Blackfire.php b/system/libs/Twig/Profiler/Dumper/BlackfireDumper.php old mode 100755 new mode 100644 similarity index 77% rename from system/libs/Twig/Profiler/Dumper/Blackfire.php rename to system/libs/Twig/Profiler/Dumper/BlackfireDumper.php index 7a33baf2..a1c3c7bc --- a/system/libs/Twig/Profiler/Dumper/Blackfire.php +++ b/system/libs/Twig/Profiler/Dumper/BlackfireDumper.php @@ -9,16 +9,20 @@ * file that was distributed with this source code. */ +namespace Twig\Profiler\Dumper; + +use Twig\Profiler\Profile; + /** * @author Fabien Potencier * * @final */ -class Twig_Profiler_Dumper_Blackfire +class BlackfireDumper { - public function dump(Twig_Profiler_Profile $profile) + public function dump(Profile $profile) { - $data = array(); + $data = []; $this->dumpProfile('main()', $profile, $data); $this->dumpChildren('main()', $profile, $data); @@ -38,7 +42,7 @@ EOF; return $str; } - private function dumpChildren($parent, Twig_Profiler_Profile $profile, &$data) + private function dumpChildren($parent, Profile $profile, &$data) { foreach ($profile as $p) { if ($p->isTemplate()) { @@ -51,22 +55,22 @@ EOF; } } - private function dumpProfile($edge, Twig_Profiler_Profile $profile, &$data) + private function dumpProfile($edge, Profile $profile, &$data) { if (isset($data[$edge])) { - $data[$edge]['ct'] += 1; + ++$data[$edge]['ct']; $data[$edge]['wt'] += floor($profile->getDuration() * 1000000); $data[$edge]['mu'] += $profile->getMemoryUsage(); $data[$edge]['pmu'] += $profile->getPeakMemoryUsage(); } else { - $data[$edge] = array( + $data[$edge] = [ 'ct' => 1, 'wt' => floor($profile->getDuration() * 1000000), 'mu' => $profile->getMemoryUsage(), 'pmu' => $profile->getPeakMemoryUsage(), - ); + ]; } } } -class_alias('Twig_Profiler_Dumper_Blackfire', 'Twig\Profiler\Dumper\BlackfireDumper', false); +class_alias('Twig\Profiler\Dumper\BlackfireDumper', 'Twig_Profiler_Dumper_Blackfire'); diff --git a/system/libs/Twig/Profiler/Dumper/Html.php b/system/libs/Twig/Profiler/Dumper/HtmlDumper.php old mode 100755 new mode 100644 similarity index 68% rename from system/libs/Twig/Profiler/Dumper/Html.php rename to system/libs/Twig/Profiler/Dumper/HtmlDumper.php index b57a2551..c70b405b --- a/system/libs/Twig/Profiler/Dumper/Html.php +++ b/system/libs/Twig/Profiler/Dumper/HtmlDumper.php @@ -9,39 +9,43 @@ * file that was distributed with this source code. */ +namespace Twig\Profiler\Dumper; + +use Twig\Profiler\Profile; + /** * @author Fabien Potencier * * @final */ -class Twig_Profiler_Dumper_Html extends Twig_Profiler_Dumper_Base +class HtmlDumper extends BaseDumper { - private static $colors = array( + private static $colors = [ 'block' => '#dfd', 'macro' => '#ddf', 'template' => '#ffd', 'big' => '#d44', - ); + ]; - public function dump(Twig_Profiler_Profile $profile) + public function dump(Profile $profile) { return '
'.parent::dump($profile).'
'; } - protected function formatTemplate(Twig_Profiler_Profile $profile, $prefix) + protected function formatTemplate(Profile $profile, $prefix) { return sprintf('%s└ %s', $prefix, self::$colors['template'], $profile->getTemplate()); } - protected function formatNonTemplate(Twig_Profiler_Profile $profile, $prefix) + protected function formatNonTemplate(Profile $profile, $prefix) { return sprintf('%s└ %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), isset(self::$colors[$profile->getType()]) ? self::$colors[$profile->getType()] : 'auto', $profile->getName()); } - protected function formatTime(Twig_Profiler_Profile $profile, $percent) + protected function formatTime(Profile $profile, $percent) { return sprintf('%.2fms/%.0f%%', $percent > 20 ? self::$colors['big'] : 'auto', $profile->getDuration() * 1000, $percent); } } -class_alias('Twig_Profiler_Dumper_Html', 'Twig\Profiler\Dumper\HtmlDumper', false); +class_alias('Twig\Profiler\Dumper\HtmlDumper', 'Twig_Profiler_Dumper_Html'); diff --git a/system/libs/Twig/Profiler/Dumper/Text.php b/system/libs/Twig/Profiler/Dumper/TextDumper.php old mode 100755 new mode 100644 similarity index 60% rename from system/libs/Twig/Profiler/Dumper/Text.php rename to system/libs/Twig/Profiler/Dumper/TextDumper.php index 69d2c4bf..c6b51589 --- a/system/libs/Twig/Profiler/Dumper/Text.php +++ b/system/libs/Twig/Profiler/Dumper/TextDumper.php @@ -9,27 +9,31 @@ * file that was distributed with this source code. */ +namespace Twig\Profiler\Dumper; + +use Twig\Profiler\Profile; + /** * @author Fabien Potencier * * @final */ -class Twig_Profiler_Dumper_Text extends Twig_Profiler_Dumper_Base +class TextDumper extends BaseDumper { - protected function formatTemplate(Twig_Profiler_Profile $profile, $prefix) + protected function formatTemplate(Profile $profile, $prefix) { return sprintf('%s└ %s', $prefix, $profile->getTemplate()); } - protected function formatNonTemplate(Twig_Profiler_Profile $profile, $prefix) + protected function formatNonTemplate(Profile $profile, $prefix) { return sprintf('%s└ %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), $profile->getName()); } - protected function formatTime(Twig_Profiler_Profile $profile, $percent) + protected function formatTime(Profile $profile, $percent) { return sprintf('%.2fms/%.0f%%', $profile->getDuration() * 1000, $percent); } } -class_alias('Twig_Profiler_Dumper_Text', 'Twig\Profiler\Dumper\TextDumper', false); +class_alias('Twig\Profiler\Dumper\TextDumper', 'Twig_Profiler_Dumper_Text'); diff --git a/system/libs/Twig/Profiler/Node/EnterProfile.php b/system/libs/Twig/Profiler/Node/EnterProfileNode.php old mode 100755 new mode 100644 similarity index 58% rename from system/libs/Twig/Profiler/Node/EnterProfile.php rename to system/libs/Twig/Profiler/Node/EnterProfileNode.php index 69c8f797..8ffd3dc7 --- a/system/libs/Twig/Profiler/Node/EnterProfile.php +++ b/system/libs/Twig/Profiler/Node/EnterProfileNode.php @@ -9,25 +9,30 @@ * file that was distributed with this source code. */ +namespace Twig\Profiler\Node; + +use Twig\Compiler; +use Twig\Node\Node; + /** * Represents a profile enter node. * * @author Fabien Potencier */ -class Twig_Profiler_Node_EnterProfile extends Twig_Node +class EnterProfileNode extends Node { public function __construct($extensionName, $type, $name, $varName) { - parent::__construct(array(), array('extension_name' => $extensionName, 'name' => $name, 'type' => $type, 'var_name' => $varName)); + parent::__construct([], ['extension_name' => $extensionName, 'name' => $name, 'type' => $type, 'var_name' => $varName]); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->write(sprintf('$%s = $this->env->getExtension(', $this->getAttribute('var_name'))) ->repr($this->getAttribute('extension_name')) ->raw(");\n") - ->write(sprintf('$%s->enter($%s = new Twig_Profiler_Profile($this->getTemplateName(), ', $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof')) + ->write(sprintf('$%s->enter($%s = new \Twig\Profiler\Profile($this->getTemplateName(), ', $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof')) ->repr($this->getAttribute('type')) ->raw(', ') ->repr($this->getAttribute('name')) @@ -36,4 +41,4 @@ class Twig_Profiler_Node_EnterProfile extends Twig_Node } } -class_alias('Twig_Profiler_Node_EnterProfile', 'Twig\Profiler\Node\EnterProfileNode', false); +class_alias('Twig\Profiler\Node\EnterProfileNode', 'Twig_Profiler_Node_EnterProfile'); diff --git a/system/libs/Twig/Profiler/Node/LeaveProfile.php b/system/libs/Twig/Profiler/Node/LeaveProfileNode.php old mode 100755 new mode 100644 similarity index 64% rename from system/libs/Twig/Profiler/Node/LeaveProfile.php rename to system/libs/Twig/Profiler/Node/LeaveProfileNode.php index d1d6a7cc..3b7a74d0 --- a/system/libs/Twig/Profiler/Node/LeaveProfile.php +++ b/system/libs/Twig/Profiler/Node/LeaveProfileNode.php @@ -9,19 +9,24 @@ * file that was distributed with this source code. */ +namespace Twig\Profiler\Node; + +use Twig\Compiler; +use Twig\Node\Node; + /** * Represents a profile leave node. * * @author Fabien Potencier */ -class Twig_Profiler_Node_LeaveProfile extends Twig_Node +class LeaveProfileNode extends Node { public function __construct($varName) { - parent::__construct(array(), array('var_name' => $varName)); + parent::__construct([], ['var_name' => $varName]); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->write("\n") @@ -30,4 +35,4 @@ class Twig_Profiler_Node_LeaveProfile extends Twig_Node } } -class_alias('Twig_Profiler_Node_LeaveProfile', 'Twig\Profiler\Node\LeaveProfileNode', false); +class_alias('Twig\Profiler\Node\LeaveProfileNode', 'Twig_Profiler_Node_LeaveProfile'); diff --git a/system/libs/Twig/Profiler/NodeVisitor/Profiler.php b/system/libs/Twig/Profiler/NodeVisitor/Profiler.php deleted file mode 100755 index a395ae7f..00000000 --- a/system/libs/Twig/Profiler/NodeVisitor/Profiler.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * @final - */ -class Twig_Profiler_NodeVisitor_Profiler extends Twig_BaseNodeVisitor -{ - private $extensionName; - - public function __construct($extensionName) - { - $this->extensionName = $extensionName; - } - - protected function doEnterNode(Twig_Node $node, Twig_Environment $env) - { - return $node; - } - - protected function doLeaveNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_Module) { - $varName = $this->getVarName(); - $node->setNode('display_start', new Twig_Node(array(new Twig_Profiler_Node_EnterProfile($this->extensionName, Twig_Profiler_Profile::TEMPLATE, $node->getTemplateName(), $varName), $node->getNode('display_start')))); - $node->setNode('display_end', new Twig_Node(array(new Twig_Profiler_Node_LeaveProfile($varName), $node->getNode('display_end')))); - } elseif ($node instanceof Twig_Node_Block) { - $varName = $this->getVarName(); - $node->setNode('body', new Twig_Node_Body(array( - new Twig_Profiler_Node_EnterProfile($this->extensionName, Twig_Profiler_Profile::BLOCK, $node->getAttribute('name'), $varName), - $node->getNode('body'), - new Twig_Profiler_Node_LeaveProfile($varName), - ))); - } elseif ($node instanceof Twig_Node_Macro) { - $varName = $this->getVarName(); - $node->setNode('body', new Twig_Node_Body(array( - new Twig_Profiler_Node_EnterProfile($this->extensionName, Twig_Profiler_Profile::MACRO, $node->getAttribute('name'), $varName), - $node->getNode('body'), - new Twig_Profiler_Node_LeaveProfile($varName), - ))); - } - - return $node; - } - - private function getVarName() - { - return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false)); - } - - public function getPriority() - { - return 0; - } -} - -class_alias('Twig_Profiler_NodeVisitor_Profiler', 'Twig\Profiler\NodeVisitor\ProfilerNodeVisitor', false); diff --git a/system/libs/Twig/Profiler/NodeVisitor/ProfilerNodeVisitor.php b/system/libs/Twig/Profiler/NodeVisitor/ProfilerNodeVisitor.php new file mode 100644 index 00000000..41ca9e1f --- /dev/null +++ b/system/libs/Twig/Profiler/NodeVisitor/ProfilerNodeVisitor.php @@ -0,0 +1,80 @@ + + * + * @final + */ +class ProfilerNodeVisitor extends AbstractNodeVisitor +{ + private $extensionName; + + public function __construct($extensionName) + { + $this->extensionName = $extensionName; + } + + protected function doEnterNode(Node $node, Environment $env) + { + return $node; + } + + protected function doLeaveNode(Node $node, Environment $env) + { + if ($node instanceof ModuleNode) { + $varName = $this->getVarName(); + $node->setNode('display_start', new Node([new EnterProfileNode($this->extensionName, Profile::TEMPLATE, $node->getTemplateName(), $varName), $node->getNode('display_start')])); + $node->setNode('display_end', new Node([new LeaveProfileNode($varName), $node->getNode('display_end')])); + } elseif ($node instanceof BlockNode) { + $varName = $this->getVarName(); + $node->setNode('body', new BodyNode([ + new EnterProfileNode($this->extensionName, Profile::BLOCK, $node->getAttribute('name'), $varName), + $node->getNode('body'), + new LeaveProfileNode($varName), + ])); + } elseif ($node instanceof MacroNode) { + $varName = $this->getVarName(); + $node->setNode('body', new BodyNode([ + new EnterProfileNode($this->extensionName, Profile::MACRO, $node->getAttribute('name'), $varName), + $node->getNode('body'), + new LeaveProfileNode($varName), + ])); + } + + return $node; + } + + private function getVarName() + { + return sprintf('__internal_%s', hash('sha256', $this->extensionName)); + } + + public function getPriority() + { + return 0; + } +} + +class_alias('Twig\Profiler\NodeVisitor\ProfilerNodeVisitor', 'Twig_Profiler_NodeVisitor_Profiler'); diff --git a/system/libs/Twig/Profiler/Profile.php b/system/libs/Twig/Profiler/Profile.php index 3fdc1a8a..d83da40a 100755 --- a/system/libs/Twig/Profiler/Profile.php +++ b/system/libs/Twig/Profiler/Profile.php @@ -9,12 +9,14 @@ * file that was distributed with this source code. */ +namespace Twig\Profiler; + /** * @author Fabien Potencier * * @final */ -class Twig_Profiler_Profile implements IteratorAggregate, Serializable +class Profile implements \IteratorAggregate, \Serializable { const ROOT = 'ROOT'; const BLOCK = 'block'; @@ -24,9 +26,9 @@ class Twig_Profiler_Profile implements IteratorAggregate, Serializable private $template; private $name; private $type; - private $starts = array(); - private $ends = array(); - private $profiles = array(); + private $starts = []; + private $ends = []; + private $profiles = []; public function __construct($template = 'main', $type = self::ROOT, $name = 'main') { @@ -76,7 +78,7 @@ class Twig_Profiler_Profile implements IteratorAggregate, Serializable return $this->profiles; } - public function addProfile(Twig_Profiler_Profile $profile) + public function addProfile(self $profile) { $this->profiles[] = $profile; } @@ -84,7 +86,7 @@ class Twig_Profiler_Profile implements IteratorAggregate, Serializable /** * Returns the duration in microseconds. * - * @return int + * @return float */ public function getDuration() { @@ -126,11 +128,11 @@ class Twig_Profiler_Profile implements IteratorAggregate, Serializable */ public function enter() { - $this->starts = array( + $this->starts = [ 'wt' => microtime(true), 'mu' => memory_get_usage(), 'pmu' => memory_get_peak_usage(), - ); + ]; } /** @@ -138,33 +140,49 @@ class Twig_Profiler_Profile implements IteratorAggregate, Serializable */ public function leave() { - $this->ends = array( + $this->ends = [ 'wt' => microtime(true), 'mu' => memory_get_usage(), 'pmu' => memory_get_peak_usage(), - ); + ]; } public function reset() { - $this->starts = $this->ends = $this->profiles = array(); + $this->starts = $this->ends = $this->profiles = []; $this->enter(); } public function getIterator() { - return new ArrayIterator($this->profiles); + return new \ArrayIterator($this->profiles); } public function serialize() { - return serialize(array($this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles)); + return serialize($this->__serialize()); } public function unserialize($data) { - list($this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles) = unserialize($data); + $this->__unserialize(unserialize($data)); + } + + /** + * @internal + */ + public function __serialize() + { + return [$this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles]; + } + + /** + * @internal + */ + public function __unserialize(array $data) + { + list($this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles) = $data; } } -class_alias('Twig_Profiler_Profile', 'Twig\Profiler\Profile', false); +class_alias('Twig\Profiler\Profile', 'Twig_Profiler_Profile'); diff --git a/system/libs/Twig/ContainerRuntimeLoader.php b/system/libs/Twig/RuntimeLoader/ContainerRuntimeLoader.php similarity index 81% rename from system/libs/Twig/ContainerRuntimeLoader.php rename to system/libs/Twig/RuntimeLoader/ContainerRuntimeLoader.php index 814ab58b..04a6602f 100644 --- a/system/libs/Twig/ContainerRuntimeLoader.php +++ b/system/libs/Twig/RuntimeLoader/ContainerRuntimeLoader.php @@ -9,6 +9,8 @@ * file that was distributed with this source code. */ +namespace Twig\RuntimeLoader; + use Psr\Container\ContainerInterface; /** @@ -19,7 +21,7 @@ use Psr\Container\ContainerInterface; * @author Fabien Potencier * @author Robin Chalas */ -class Twig_ContainerRuntimeLoader implements Twig_RuntimeLoaderInterface +class ContainerRuntimeLoader implements RuntimeLoaderInterface { private $container; @@ -36,4 +38,4 @@ class Twig_ContainerRuntimeLoader implements Twig_RuntimeLoaderInterface } } -class_alias('Twig_ContainerRuntimeLoader', 'Twig\RuntimeLoader\ContainerRuntimeLoader', false); +class_alias('Twig\RuntimeLoader\ContainerRuntimeLoader', 'Twig_ContainerRuntimeLoader'); diff --git a/system/libs/Twig/FactoryRuntimeLoader.php b/system/libs/Twig/RuntimeLoader/FactoryRuntimeLoader.php similarity index 75% rename from system/libs/Twig/FactoryRuntimeLoader.php rename to system/libs/Twig/RuntimeLoader/FactoryRuntimeLoader.php index 2cdaded1..43b5f24e 100644 --- a/system/libs/Twig/FactoryRuntimeLoader.php +++ b/system/libs/Twig/RuntimeLoader/FactoryRuntimeLoader.php @@ -9,19 +9,21 @@ * file that was distributed with this source code. */ +namespace Twig\RuntimeLoader; + /** * Lazy loads the runtime implementations for a Twig element. * * @author Robin Chalas */ -class Twig_FactoryRuntimeLoader implements Twig_RuntimeLoaderInterface +class FactoryRuntimeLoader implements RuntimeLoaderInterface { private $map; /** * @param array $map An array where keys are class names and values factory callables */ - public function __construct($map = array()) + public function __construct($map = []) { $this->map = $map; } @@ -36,4 +38,4 @@ class Twig_FactoryRuntimeLoader implements Twig_RuntimeLoaderInterface } } -class_alias('Twig_FactoryRuntimeLoader', 'Twig\RuntimeLoader\FactoryRuntimeLoader', false); +class_alias('Twig\RuntimeLoader\FactoryRuntimeLoader', 'Twig_FactoryRuntimeLoader'); diff --git a/system/libs/Twig/RuntimeLoaderInterface.php b/system/libs/Twig/RuntimeLoader/RuntimeLoaderInterface.php similarity index 81% rename from system/libs/Twig/RuntimeLoaderInterface.php rename to system/libs/Twig/RuntimeLoader/RuntimeLoaderInterface.php index f5eb14e0..4eb5ad85 100644 --- a/system/libs/Twig/RuntimeLoaderInterface.php +++ b/system/libs/Twig/RuntimeLoader/RuntimeLoaderInterface.php @@ -9,12 +9,14 @@ * file that was distributed with this source code. */ +namespace Twig\RuntimeLoader; + /** * Creates runtime implementations for Twig elements (filters/functions/tests). * * @author Fabien Potencier */ -interface Twig_RuntimeLoaderInterface +interface RuntimeLoaderInterface { /** * Creates the runtime implementation of a Twig element (filter/function/test). @@ -26,4 +28,4 @@ interface Twig_RuntimeLoaderInterface public function load($class); } -class_alias('Twig_RuntimeLoaderInterface', 'Twig\RuntimeLoader\RuntimeLoaderInterface', false); +class_alias('Twig\RuntimeLoader\RuntimeLoaderInterface', 'Twig_RuntimeLoaderInterface'); diff --git a/system/libs/Twig/Sandbox/SecurityError.php b/system/libs/Twig/Sandbox/SecurityError.php index b6707e38..5f96d46b 100755 --- a/system/libs/Twig/Sandbox/SecurityError.php +++ b/system/libs/Twig/Sandbox/SecurityError.php @@ -9,13 +9,17 @@ * file that was distributed with this source code. */ +namespace Twig\Sandbox; + +use Twig\Error\Error; + /** * Exception thrown when a security error occurs at runtime. * * @author Fabien Potencier */ -class Twig_Sandbox_SecurityError extends Twig_Error +class SecurityError extends Error { } -class_alias('Twig_Sandbox_SecurityError', 'Twig\Sandbox\SecurityError', false); +class_alias('Twig\Sandbox\SecurityError', 'Twig_Sandbox_SecurityError'); diff --git a/system/libs/Twig/Sandbox/SecurityNotAllowedFilterError.php b/system/libs/Twig/Sandbox/SecurityNotAllowedFilterError.php index 0ba33276..fa0fdee7 100755 --- a/system/libs/Twig/Sandbox/SecurityNotAllowedFilterError.php +++ b/system/libs/Twig/Sandbox/SecurityNotAllowedFilterError.php @@ -9,16 +9,18 @@ * file that was distributed with this source code. */ +namespace Twig\Sandbox; + /** * Exception thrown when a not allowed filter is used in a template. * * @author Martin Hasoň */ -class Twig_Sandbox_SecurityNotAllowedFilterError extends Twig_Sandbox_SecurityError +class SecurityNotAllowedFilterError extends SecurityError { private $filterName; - public function __construct($message, $functionName, $lineno = -1, $filename = null, Exception $previous = null) + public function __construct($message, $functionName, $lineno = -1, $filename = null, \Exception $previous = null) { parent::__construct($message, $lineno, $filename, $previous); $this->filterName = $functionName; @@ -30,4 +32,4 @@ class Twig_Sandbox_SecurityNotAllowedFilterError extends Twig_Sandbox_SecurityEr } } -class_alias('Twig_Sandbox_SecurityNotAllowedFilterError', 'Twig\Sandbox\SecurityNotAllowedFilterError', false); +class_alias('Twig\Sandbox\SecurityNotAllowedFilterError', 'Twig_Sandbox_SecurityNotAllowedFilterError'); diff --git a/system/libs/Twig/Sandbox/SecurityNotAllowedFunctionError.php b/system/libs/Twig/Sandbox/SecurityNotAllowedFunctionError.php index aa391429..8f23f93a 100755 --- a/system/libs/Twig/Sandbox/SecurityNotAllowedFunctionError.php +++ b/system/libs/Twig/Sandbox/SecurityNotAllowedFunctionError.php @@ -9,16 +9,18 @@ * file that was distributed with this source code. */ +namespace Twig\Sandbox; + /** * Exception thrown when a not allowed function is used in a template. * * @author Martin Hasoň */ -class Twig_Sandbox_SecurityNotAllowedFunctionError extends Twig_Sandbox_SecurityError +class SecurityNotAllowedFunctionError extends SecurityError { private $functionName; - public function __construct($message, $functionName, $lineno = -1, $filename = null, Exception $previous = null) + public function __construct($message, $functionName, $lineno = -1, $filename = null, \Exception $previous = null) { parent::__construct($message, $lineno, $filename, $previous); $this->functionName = $functionName; @@ -30,4 +32,4 @@ class Twig_Sandbox_SecurityNotAllowedFunctionError extends Twig_Sandbox_Security } } -class_alias('Twig_Sandbox_SecurityNotAllowedFunctionError', 'Twig\Sandbox\SecurityNotAllowedFunctionError', false); +class_alias('Twig\Sandbox\SecurityNotAllowedFunctionError', 'Twig_Sandbox_SecurityNotAllowedFunctionError'); diff --git a/system/libs/Twig/Sandbox/SecurityNotAllowedMethodError.php b/system/libs/Twig/Sandbox/SecurityNotAllowedMethodError.php index 93012fe9..62e13f49 100644 --- a/system/libs/Twig/Sandbox/SecurityNotAllowedMethodError.php +++ b/system/libs/Twig/Sandbox/SecurityNotAllowedMethodError.php @@ -9,17 +9,19 @@ * file that was distributed with this source code. */ +namespace Twig\Sandbox; + /** * Exception thrown when a not allowed class method is used in a template. * * @author Kit Burton-Senior */ -class Twig_Sandbox_SecurityNotAllowedMethodError extends Twig_Sandbox_SecurityError +class SecurityNotAllowedMethodError extends SecurityError { private $className; private $methodName; - public function __construct($message, $className, $methodName, $lineno = -1, $filename = null, Exception $previous = null) + public function __construct($message, $className, $methodName, $lineno = -1, $filename = null, \Exception $previous = null) { parent::__construct($message, $lineno, $filename, $previous); $this->className = $className; @@ -37,4 +39,4 @@ class Twig_Sandbox_SecurityNotAllowedMethodError extends Twig_Sandbox_SecurityEr } } -class_alias('Twig_Sandbox_SecurityNotAllowedMethodError', 'Twig\Sandbox\SecurityNotAllowedMethodError', false); +class_alias('Twig\Sandbox\SecurityNotAllowedMethodError', 'Twig_Sandbox_SecurityNotAllowedMethodError'); diff --git a/system/libs/Twig/Sandbox/SecurityNotAllowedPropertyError.php b/system/libs/Twig/Sandbox/SecurityNotAllowedPropertyError.php index f27969c1..3bf53057 100644 --- a/system/libs/Twig/Sandbox/SecurityNotAllowedPropertyError.php +++ b/system/libs/Twig/Sandbox/SecurityNotAllowedPropertyError.php @@ -9,17 +9,19 @@ * file that was distributed with this source code. */ +namespace Twig\Sandbox; + /** * Exception thrown when a not allowed class property is used in a template. * * @author Kit Burton-Senior */ -class Twig_Sandbox_SecurityNotAllowedPropertyError extends Twig_Sandbox_SecurityError +class SecurityNotAllowedPropertyError extends SecurityError { private $className; private $propertyName; - public function __construct($message, $className, $propertyName, $lineno = -1, $filename = null, Exception $previous = null) + public function __construct($message, $className, $propertyName, $lineno = -1, $filename = null, \Exception $previous = null) { parent::__construct($message, $lineno, $filename, $previous); $this->className = $className; @@ -37,4 +39,4 @@ class Twig_Sandbox_SecurityNotAllowedPropertyError extends Twig_Sandbox_Security } } -class_alias('Twig_Sandbox_SecurityNotAllowedPropertyError', 'Twig\Sandbox\SecurityNotAllowedPropertyError', false); +class_alias('Twig\Sandbox\SecurityNotAllowedPropertyError', 'Twig_Sandbox_SecurityNotAllowedPropertyError'); diff --git a/system/libs/Twig/Sandbox/SecurityNotAllowedTagError.php b/system/libs/Twig/Sandbox/SecurityNotAllowedTagError.php index 4bbd2238..de283b40 100755 --- a/system/libs/Twig/Sandbox/SecurityNotAllowedTagError.php +++ b/system/libs/Twig/Sandbox/SecurityNotAllowedTagError.php @@ -9,16 +9,18 @@ * file that was distributed with this source code. */ +namespace Twig\Sandbox; + /** * Exception thrown when a not allowed tag is used in a template. * * @author Martin Hasoň */ -class Twig_Sandbox_SecurityNotAllowedTagError extends Twig_Sandbox_SecurityError +class SecurityNotAllowedTagError extends SecurityError { private $tagName; - public function __construct($message, $tagName, $lineno = -1, $filename = null, Exception $previous = null) + public function __construct($message, $tagName, $lineno = -1, $filename = null, \Exception $previous = null) { parent::__construct($message, $lineno, $filename, $previous); $this->tagName = $tagName; @@ -30,4 +32,4 @@ class Twig_Sandbox_SecurityNotAllowedTagError extends Twig_Sandbox_SecurityError } } -class_alias('Twig_Sandbox_SecurityNotAllowedTagError', 'Twig\Sandbox\SecurityNotAllowedTagError', false); +class_alias('Twig\Sandbox\SecurityNotAllowedTagError', 'Twig_Sandbox_SecurityNotAllowedTagError'); diff --git a/system/libs/Twig/Sandbox/SecurityPolicy.php b/system/libs/Twig/Sandbox/SecurityPolicy.php index dca0b82b..31b6c348 100755 --- a/system/libs/Twig/Sandbox/SecurityPolicy.php +++ b/system/libs/Twig/Sandbox/SecurityPolicy.php @@ -9,6 +9,10 @@ * file that was distributed with this source code. */ +namespace Twig\Sandbox; + +use Twig\Markup; + /** * Represents a security policy which need to be enforced when sandbox mode is enabled. * @@ -16,7 +20,7 @@ * * @author Fabien Potencier */ -class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterface +class SecurityPolicy implements SecurityPolicyInterface { protected $allowedTags; protected $allowedFilters; @@ -24,7 +28,7 @@ class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterfac protected $allowedProperties; protected $allowedFunctions; - public function __construct(array $allowedTags = array(), array $allowedFilters = array(), array $allowedMethods = array(), array $allowedProperties = array(), array $allowedFunctions = array()) + public function __construct(array $allowedTags = [], array $allowedFilters = [], array $allowedMethods = [], array $allowedProperties = [], array $allowedFunctions = []) { $this->allowedTags = $allowedTags; $this->allowedFilters = $allowedFilters; @@ -45,9 +49,9 @@ class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterfac public function setAllowedMethods(array $methods) { - $this->allowedMethods = array(); + $this->allowedMethods = []; foreach ($methods as $class => $m) { - $this->allowedMethods[$class] = array_map('strtolower', is_array($m) ? $m : array($m)); + $this->allowedMethods[$class] = array_map('strtolower', \is_array($m) ? $m : [$m]); } } @@ -64,43 +68,43 @@ class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterfac public function checkSecurity($tags, $filters, $functions) { foreach ($tags as $tag) { - if (!in_array($tag, $this->allowedTags)) { - throw new Twig_Sandbox_SecurityNotAllowedTagError(sprintf('Tag "%s" is not allowed.', $tag), $tag); + if (!\in_array($tag, $this->allowedTags)) { + throw new SecurityNotAllowedTagError(sprintf('Tag "%s" is not allowed.', $tag), $tag); } } foreach ($filters as $filter) { - if (!in_array($filter, $this->allowedFilters)) { - throw new Twig_Sandbox_SecurityNotAllowedFilterError(sprintf('Filter "%s" is not allowed.', $filter), $filter); + if (!\in_array($filter, $this->allowedFilters)) { + throw new SecurityNotAllowedFilterError(sprintf('Filter "%s" is not allowed.', $filter), $filter); } } foreach ($functions as $function) { - if (!in_array($function, $this->allowedFunctions)) { - throw new Twig_Sandbox_SecurityNotAllowedFunctionError(sprintf('Function "%s" is not allowed.', $function), $function); + if (!\in_array($function, $this->allowedFunctions)) { + throw new SecurityNotAllowedFunctionError(sprintf('Function "%s" is not allowed.', $function), $function); } } } public function checkMethodAllowed($obj, $method) { - if ($obj instanceof Twig_TemplateInterface || $obj instanceof Twig_Markup) { - return true; + if ($obj instanceof \Twig_TemplateInterface || $obj instanceof Markup) { + return; } $allowed = false; $method = strtolower($method); foreach ($this->allowedMethods as $class => $methods) { if ($obj instanceof $class) { - $allowed = in_array($method, $methods); + $allowed = \in_array($method, $methods); break; } } if (!$allowed) { - $class = get_class($obj); - throw new Twig_Sandbox_SecurityNotAllowedMethodError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, $class), $class, $method); + $class = \get_class($obj); + throw new SecurityNotAllowedMethodError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, $class), $class, $method); } } @@ -109,17 +113,17 @@ class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterfac $allowed = false; foreach ($this->allowedProperties as $class => $properties) { if ($obj instanceof $class) { - $allowed = in_array($property, is_array($properties) ? $properties : array($properties)); + $allowed = \in_array($property, \is_array($properties) ? $properties : [$properties]); break; } } if (!$allowed) { - $class = get_class($obj); - throw new Twig_Sandbox_SecurityNotAllowedPropertyError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, $class), $class, $property); + $class = \get_class($obj); + throw new SecurityNotAllowedPropertyError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, $class), $class, $property); } } } -class_alias('Twig_Sandbox_SecurityPolicy', 'Twig\Sandbox\SecurityPolicy', false); +class_alias('Twig\Sandbox\SecurityPolicy', 'Twig_Sandbox_SecurityPolicy'); diff --git a/system/libs/Twig/Sandbox/SecurityPolicyInterface.php b/system/libs/Twig/Sandbox/SecurityPolicyInterface.php index 88f64447..a31863f6 100755 --- a/system/libs/Twig/Sandbox/SecurityPolicyInterface.php +++ b/system/libs/Twig/Sandbox/SecurityPolicyInterface.php @@ -9,12 +9,14 @@ * file that was distributed with this source code. */ +namespace Twig\Sandbox; + /** - * Interfaces that all security policy classes must implements. + * Interface that all security policy classes must implements. * * @author Fabien Potencier */ -interface Twig_Sandbox_SecurityPolicyInterface +interface SecurityPolicyInterface { public function checkSecurity($tags, $filters, $functions); @@ -23,4 +25,4 @@ interface Twig_Sandbox_SecurityPolicyInterface public function checkPropertyAllowed($obj, $method); } -class_alias('Twig_Sandbox_SecurityPolicyInterface', 'Twig\Sandbox\SecurityPolicyInterface', false); +class_alias('Twig\Sandbox\SecurityPolicyInterface', 'Twig_Sandbox_SecurityPolicyInterface'); diff --git a/system/libs/Twig/Source.php b/system/libs/Twig/Source.php index bd8d869f..32a82163 100644 --- a/system/libs/Twig/Source.php +++ b/system/libs/Twig/Source.php @@ -9,6 +9,8 @@ * file that was distributed with this source code. */ +namespace Twig; + /** * Holds information about a non-compiled Twig template. * @@ -16,7 +18,7 @@ * * @author Fabien Potencier */ -class Twig_Source +class Source { private $code; private $name; @@ -50,4 +52,4 @@ class Twig_Source } } -class_alias('Twig_Source', 'Twig\Source', false); +class_alias('Twig\Source', 'Twig_Source'); diff --git a/system/libs/Twig/Template.php b/system/libs/Twig/Template.php index 64563419..3f7447c1 100755 --- a/system/libs/Twig/Template.php +++ b/system/libs/Twig/Template.php @@ -10,31 +10,38 @@ * file that was distributed with this source code. */ +namespace Twig; + +use Twig\Error\Error; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; + /** * Default base class for compiled templates. * * This class is an implementation detail of how template compilation currently * works, which might change. It should never be used directly. Use $twig->load() - * instead, which returns an instance of Twig_TemplateWrapper. + * instead, which returns an instance of \Twig\TemplateWrapper. * * @author Fabien Potencier * * @internal */ -abstract class Twig_Template implements Twig_TemplateInterface +abstract class Template implements \Twig_TemplateInterface { /** * @internal */ - protected static $cache = array(); + protected static $cache = []; protected $parent; - protected $parents = array(); + protected $parents = []; protected $env; - protected $blocks = array(); - protected $traits = array(); + protected $blocks = []; + protected $traits = []; + protected $sandbox; - public function __construct(Twig_Environment $env) + public function __construct(Environment $env) { $this->env = $env; } @@ -58,12 +65,10 @@ abstract class Twig_Template implements Twig_TemplateInterface * Returns debug information about the template. * * @return array Debug information - * - * @internal */ public function getDebugInfo() { - return array(); + return []; } /** @@ -83,11 +88,11 @@ abstract class Twig_Template implements Twig_TemplateInterface /** * Returns information about the original template source code. * - * @return Twig_Source + * @return Source */ public function getSourceContext() { - return new Twig_Source('', $this->getTemplateName()); + return new Source('', $this->getTemplateName()); } /** @@ -108,7 +113,7 @@ abstract class Twig_Template implements Twig_TemplateInterface * * @param array $context * - * @return Twig_TemplateInterface|false The parent template or false if there is no parent + * @return \Twig_TemplateInterface|TemplateWrapper|false The parent template or false if there is no parent * * @internal */ @@ -125,14 +130,14 @@ abstract class Twig_Template implements Twig_TemplateInterface return false; } - if ($parent instanceof self) { - return $this->parents[$parent->getTemplateName()] = $parent; + if ($parent instanceof self || $parent instanceof TemplateWrapper) { + return $this->parents[$parent->getSourceContext()->getName()] = $parent; } if (!isset($this->parents[$parent])) { $this->parents[$parent] = $this->loadTemplate($parent); } - } catch (Twig_Error_Loader $e) { + } catch (LoaderError $e) { $e->setSourceContext(null); $e->guess(); @@ -161,10 +166,8 @@ abstract class Twig_Template implements Twig_TemplateInterface * @param string $name The block name to display from the parent * @param array $context The context * @param array $blocks The current set of blocks - * - * @internal */ - public function displayParentBlock($name, array $context, array $blocks = array()) + public function displayParentBlock($name, array $context, array $blocks = []) { $name = (string) $name; @@ -173,7 +176,7 @@ abstract class Twig_Template implements Twig_TemplateInterface } elseif (false !== $parent = $this->getParent($context)) { $parent->displayBlock($name, $context, $blocks, false); } else { - throw new Twig_Error_Runtime(sprintf('The template has no parent and no traits defining the "%s" block.', $name), -1, $this->getSourceContext()); + throw new RuntimeError(sprintf('The template has no parent and no traits defining the "%s" block.', $name), -1, $this->getSourceContext()); } } @@ -187,10 +190,8 @@ abstract class Twig_Template implements Twig_TemplateInterface * @param array $context The context * @param array $blocks The current set of blocks * @param bool $useBlocks Whether to use the current set of blocks - * - * @internal */ - public function displayBlock($name, array $context, array $blocks = array(), $useBlocks = true) + public function displayBlock($name, array $context, array $blocks = [], $useBlocks = true) { $name = (string) $name; @@ -207,27 +208,29 @@ abstract class Twig_Template implements Twig_TemplateInterface // avoid RCEs when sandbox is enabled if (null !== $template && !$template instanceof self) { - throw new LogicException('A block must be a method on a Twig_Template instance.'); + throw new \LogicException('A block must be a method on a \Twig\Template instance.'); } if (null !== $template) { try { $template->$block($context, $blocks); - } catch (Twig_Error $e) { + } catch (Error $e) { if (!$e->getSourceContext()) { $e->setSourceContext($template->getSourceContext()); } - // this is mostly useful for Twig_Error_Loader exceptions - // see Twig_Error_Loader - if (false === $e->getTemplateLine()) { - $e->setTemplateLine(-1); + // this is mostly useful for \Twig\Error\LoaderError exceptions + // see \Twig\Error\LoaderError + if (-1 === $e->getTemplateLine()) { $e->guess(); } throw $e; - } catch (Exception $e) { - throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getSourceContext(), $e); + } catch (\Exception $e) { + $e = new RuntimeError(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getSourceContext(), $e); + $e->guess(); + + throw $e; } } elseif (false !== $parent = $this->getParent($context)) { $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks), false); @@ -247,12 +250,14 @@ abstract class Twig_Template implements Twig_TemplateInterface * @param array $blocks The current set of blocks * * @return string The rendered block - * - * @internal */ - public function renderParentBlock($name, array $context, array $blocks = array()) + public function renderParentBlock($name, array $context, array $blocks = []) { - ob_start(); + if ($this->env->isDebug()) { + ob_start(); + } else { + ob_start(function () { return ''; }); + } $this->displayParentBlock($name, $context, $blocks); return ob_get_clean(); @@ -270,12 +275,14 @@ abstract class Twig_Template implements Twig_TemplateInterface * @param bool $useBlocks Whether to use the current set of blocks * * @return string The rendered block - * - * @internal */ - public function renderBlock($name, array $context, array $blocks = array(), $useBlocks = true) + public function renderBlock($name, array $context, array $blocks = [], $useBlocks = true) { - ob_start(); + if ($this->env->isDebug()) { + ob_start(); + } else { + ob_start(function () { return ''; }); + } $this->displayBlock($name, $context, $blocks, $useBlocks); return ob_get_clean(); @@ -292,10 +299,8 @@ abstract class Twig_Template implements Twig_TemplateInterface * @param array $blocks The current set of blocks * * @return bool true if the block exists, false otherwise - * - * @internal */ - public function hasBlock($name, array $context = null, array $blocks = array()) + public function hasBlock($name, array $context = null, array $blocks = []) { if (null === $context) { @trigger_error('The '.__METHOD__.' method is internal and should never be called; calling it directly is deprecated since version 1.28 and won\'t be possible anymore in 2.0.', E_USER_DEPRECATED); @@ -328,10 +333,8 @@ abstract class Twig_Template implements Twig_TemplateInterface * @param array $blocks The current set of blocks * * @return array An array of block names - * - * @internal */ - public function getBlockNames(array $context = null, array $blocks = array()) + public function getBlockNames(array $context = null, array $blocks = []) { if (null === $context) { @trigger_error('The '.__METHOD__.' method is internal and should never be called; calling it directly is deprecated since version 1.28 and won\'t be possible anymore in 2.0.', E_USER_DEPRECATED); @@ -348,28 +351,36 @@ abstract class Twig_Template implements Twig_TemplateInterface return array_unique($names); } + /** + * @return Template|TemplateWrapper + */ protected function loadTemplate($template, $templateName = null, $line = null, $index = null) { try { - if (is_array($template)) { + if (\is_array($template)) { return $this->env->resolveTemplate($template); } - if ($template instanceof self) { + if ($template instanceof self || $template instanceof TemplateWrapper) { return $template; } - if ($template instanceof Twig_TemplateWrapper) { - return $template; + if ($template === $this->getTemplateName()) { + $class = \get_class($this); + if (false !== $pos = strrpos($class, '___', -1)) { + $class = substr($class, 0, $pos); + } + + return $this->env->loadClass($class, $template, $index); } return $this->env->loadTemplate($template, $index); - } catch (Twig_Error $e) { + } catch (Error $e) { if (!$e->getSourceContext()) { - $e->setSourceContext($templateName ? new Twig_Source('', $templateName) : $this->getSourceContext()); + $e->setSourceContext($templateName ? new Source('', $templateName) : $this->getSourceContext()); } - if ($e->getTemplateLine()) { + if ($e->getTemplateLine() > 0) { throw $e; } @@ -383,6 +394,16 @@ abstract class Twig_Template implements Twig_TemplateInterface } } + /** + * @internal + * + * @return Template + */ + protected function unwrap() + { + return $this; + } + /** * Returns all blocks. * @@ -390,15 +411,13 @@ abstract class Twig_Template implements Twig_TemplateInterface * directly. * * @return array An array of blocks - * - * @internal */ public function getBlocks() { return $this->blocks; } - public function display(array $context, array $blocks = array()) + public function display(array $context, array $blocks = []) { $this->displayWithErrorHandling($this->env->mergeGlobals($context), array_merge($this->blocks, $blocks)); } @@ -406,16 +425,20 @@ abstract class Twig_Template implements Twig_TemplateInterface public function render(array $context) { $level = ob_get_level(); - ob_start(); + if ($this->env->isDebug()) { + ob_start(); + } else { + ob_start(function () { return ''; }); + } try { $this->display($context); - } catch (Exception $e) { + } catch (\Exception $e) { while (ob_get_level() > $level) { ob_end_clean(); } throw $e; - } catch (Throwable $e) { + } catch (\Throwable $e) { while (ob_get_level() > $level) { ob_end_clean(); } @@ -426,25 +449,27 @@ abstract class Twig_Template implements Twig_TemplateInterface return ob_get_clean(); } - protected function displayWithErrorHandling(array $context, array $blocks = array()) + protected function displayWithErrorHandling(array $context, array $blocks = []) { try { $this->doDisplay($context, $blocks); - } catch (Twig_Error $e) { + } catch (Error $e) { if (!$e->getSourceContext()) { $e->setSourceContext($this->getSourceContext()); } - // this is mostly useful for Twig_Error_Loader exceptions - // see Twig_Error_Loader - if (false === $e->getTemplateLine()) { - $e->setTemplateLine(-1); + // this is mostly useful for \Twig\Error\LoaderError exceptions + // see \Twig\Error\LoaderError + if (-1 === $e->getTemplateLine()) { $e->guess(); } throw $e; - } catch (Exception $e) { - throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getSourceContext(), $e); + } catch (\Exception $e) { + $e = new RuntimeError(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getSourceContext(), $e); + $e->guess(); + + throw $e; } } @@ -454,7 +479,7 @@ abstract class Twig_Template implements Twig_TemplateInterface * @param array $context An array of parameters to pass to the template * @param array $blocks An array of blocks to pass to the template */ - abstract protected function doDisplay(array $context, array $blocks = array()); + abstract protected function doDisplay(array $context, array $blocks = []); /** * Returns a variable from the context. @@ -473,18 +498,18 @@ abstract class Twig_Template implements Twig_TemplateInterface * * @return mixed The content of the context variable * - * @throws Twig_Error_Runtime if the variable does not exist and Twig is running in strict mode + * @throws RuntimeError if the variable does not exist and Twig is running in strict mode * * @internal */ final protected function getContext($context, $item, $ignoreStrictCheck = false) { - if (!array_key_exists($item, $context)) { + if (!\array_key_exists($item, $context)) { if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { return; } - throw new Twig_Error_Runtime(sprintf('Variable "%s" does not exist.', $item), -1, $this->getSourceContext()); + throw new RuntimeError(sprintf('Variable "%s" does not exist.', $item), -1, $this->getSourceContext()); } return $context[$item]; @@ -496,24 +521,24 @@ abstract class Twig_Template implements Twig_TemplateInterface * @param mixed $object The object or array from where to get the item * @param mixed $item The item to get from the array or object * @param array $arguments An array of arguments to pass if the item is an object method - * @param string $type The type of attribute (@see Twig_Template constants) + * @param string $type The type of attribute (@see \Twig\Template constants) * @param bool $isDefinedTest Whether this is only a defined check * @param bool $ignoreStrictCheck Whether to ignore the strict attribute check or not * * @return mixed The attribute value, or a Boolean when $isDefinedTest is true, or null when the attribute is not set and $ignoreStrictCheck is true * - * @throws Twig_Error_Runtime if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false + * @throws RuntimeError if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false * * @internal */ - protected function getAttribute($object, $item, array $arguments = array(), $type = self::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false) + protected function getAttribute($object, $item, array $arguments = [], $type = self::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false) { // array if (self::METHOD_CALL !== $type) { - $arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item; + $arrayItem = \is_bool($item) || \is_float($item) ? (int) $item : $item; - if ((is_array($object) && (isset($object[$arrayItem]) || array_key_exists($arrayItem, $object))) - || ($object instanceof ArrayAccess && isset($object[$arrayItem])) + if (((\is_array($object) || $object instanceof \ArrayObject) && (isset($object[$arrayItem]) || \array_key_exists($arrayItem, (array) $object))) + || ($object instanceof \ArrayAccess && isset($object[$arrayItem])) ) { if ($isDefinedTest) { return true; @@ -522,7 +547,7 @@ abstract class Twig_Template implements Twig_TemplateInterface return $object[$arrayItem]; } - if (self::ARRAY_CALL === $type || !is_object($object)) { + if (self::ARRAY_CALL === $type || !\is_object($object)) { if ($isDefinedTest) { return false; } @@ -531,11 +556,11 @@ abstract class Twig_Template implements Twig_TemplateInterface return; } - if ($object instanceof ArrayAccess) { - $message = sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist.', $arrayItem, get_class($object)); - } elseif (is_object($object)) { - $message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface.', $item, get_class($object)); - } elseif (is_array($object)) { + if ($object instanceof \ArrayAccess) { + $message = sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist.', $arrayItem, \get_class($object)); + } elseif (\is_object($object)) { + $message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface.', $item, \get_class($object)); + } elseif (\is_array($object)) { if (empty($object)) { $message = sprintf('Key "%s" does not exist as the array is empty.', $arrayItem); } else { @@ -545,19 +570,19 @@ abstract class Twig_Template implements Twig_TemplateInterface if (null === $object) { $message = sprintf('Impossible to access a key ("%s") on a null variable.', $item); } else { - $message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s").', $item, gettype($object), $object); + $message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); } } elseif (null === $object) { $message = sprintf('Impossible to access an attribute ("%s") on a null variable.', $item); } else { - $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s").', $item, gettype($object), $object); + $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); } - throw new Twig_Error_Runtime($message, -1, $this->getSourceContext()); + throw new RuntimeError($message, -1, $this->getSourceContext()); } } - if (!is_object($object)) { + if (!\is_object($object)) { if ($isDefinedTest) { return false; } @@ -568,38 +593,40 @@ abstract class Twig_Template implements Twig_TemplateInterface if (null === $object) { $message = sprintf('Impossible to invoke a method ("%s") on a null variable.', $item); + } elseif (\is_array($object)) { + $message = sprintf('Impossible to invoke a method ("%s") on an array.', $item); } else { - $message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").', $item, gettype($object), $object); + $message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); } - throw new Twig_Error_Runtime($message, -1, $this->getSourceContext()); + throw new RuntimeError($message, -1, $this->getSourceContext()); } // object property - 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 - if (isset($object->$item) || array_key_exists((string) $item, $object)) { + 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 + if (isset($object->$item) || \array_key_exists((string) $item, (array) $object)) { if ($isDefinedTest) { return true; } - if ($this->env->hasExtension('Twig_Extension_Sandbox')) { - $this->env->getExtension('Twig_Extension_Sandbox')->checkPropertyAllowed($object, $item); + if ($this->env->hasExtension('\Twig\Extension\SandboxExtension')) { + $this->env->getExtension('\Twig\Extension\SandboxExtension')->checkPropertyAllowed($object, $item); } return $object->$item; } } - $class = get_class($object); + $class = \get_class($object); // object method if (!isset(self::$cache[$class])) { // get_class_methods returns all methods accessible in the scope, but we only want public ones to be accessible in templates if ($object instanceof self) { - $ref = new ReflectionClass($class); - $methods = array(); + $ref = new \ReflectionClass($class); + $methods = []; - foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $refMethod) { + foreach ($ref->getMethods(\ReflectionMethod::IS_PUBLIC) as $refMethod) { // Accessing the environment from templates is forbidden to prevent untrusted changes to the environment if ('getenvironment' !== strtolower($refMethod->name)) { $methods[] = $refMethod->name; @@ -611,7 +638,7 @@ abstract class Twig_Template implements Twig_TemplateInterface // sort values to have consistent behavior, so that "get" methods win precedence over "is" methods sort($methods); - $cache = array(); + $cache = []; foreach ($methods as $method) { $cache[$method] = $method; @@ -657,15 +684,15 @@ abstract class Twig_Template implements Twig_TemplateInterface return; } - throw new Twig_Error_Runtime(sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, $class), -1, $this->getSourceContext()); + 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()); } if ($isDefinedTest) { return true; } - if ($this->env->hasExtension('Twig_Extension_Sandbox')) { - $this->env->getExtension('Twig_Extension_Sandbox')->checkMethodAllowed($object, $method); + if ($this->env->hasExtension('\Twig\Extension\SandboxExtension')) { + $this->env->getExtension('\Twig\Extension\SandboxExtension')->checkMethodAllowed($object, $method); } // Some objects throw exceptions when they have __call, and the method we try @@ -674,9 +701,9 @@ abstract class Twig_Template implements Twig_TemplateInterface if (!$arguments) { $ret = $object->$method(); } else { - $ret = call_user_func_array(array($object, $method), $arguments); + $ret = \call_user_func_array([$object, $method], $arguments); } - } catch (BadMethodCallException $e) { + } catch (\BadMethodCallException $e) { if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) { return; } @@ -684,7 +711,7 @@ abstract class Twig_Template implements Twig_TemplateInterface } // @deprecated in 1.28 - if ($object instanceof Twig_TemplateInterface) { + if ($object instanceof \Twig_TemplateInterface) { $self = $object->getTemplateName() === $this->getTemplateName(); $message = sprintf('Calling "%s" on template "%s" from template "%s" is deprecated since version 1.28 and won\'t be supported anymore in 2.0.', $item, $object->getTemplateName(), $this->getTemplateName()); if ('renderBlock' === $method || 'displayBlock' === $method) { @@ -696,11 +723,11 @@ abstract class Twig_Template implements Twig_TemplateInterface } @trigger_error($message, E_USER_DEPRECATED); - return $ret === '' ? '' : new Twig_Markup($ret, $this->env->getCharset()); + return '' === $ret ? '' : new Markup($ret, $this->env->getCharset()); } return $ret; } } -class_alias('Twig_Template', 'Twig\Template', false); +class_alias('Twig\Template', 'Twig_Template'); diff --git a/system/libs/Twig/TemplateWrapper.php b/system/libs/Twig/TemplateWrapper.php index 497f6e98..e2654094 100644 --- a/system/libs/Twig/TemplateWrapper.php +++ b/system/libs/Twig/TemplateWrapper.php @@ -9,23 +9,25 @@ * file that was distributed with this source code. */ +namespace Twig; + /** * Exposes a template to userland. * * @author Fabien Potencier */ -final class Twig_TemplateWrapper +final class TemplateWrapper { private $env; private $template; /** * This method is for internal use only and should never be called - * directly (use Twig_Environment::load() instead). + * directly (use Twig\Environment::load() instead). * * @internal */ - public function __construct(Twig_Environment $env, Twig_Template $template) + public function __construct(Environment $env, Template $template) { $this->env = $env; $this->template = $template; @@ -38,9 +40,11 @@ final class Twig_TemplateWrapper * * @return string The rendered template */ - public function render($context = array()) + public function render($context = []) { - return $this->template->render($context); + // using func_get_args() allows to not expose the blocks argument + // as it should only be used by internal code + return $this->template->render($context, \func_num_args() > 1 ? func_get_arg(1) : []); } /** @@ -48,9 +52,11 @@ final class Twig_TemplateWrapper * * @param array $context An array of parameters to pass to the template */ - public function display($context = array()) + public function display($context = []) { - $this->template->display($context); + // using func_get_args() allows to not expose the blocks argument + // as it should only be used by internal code + $this->template->display($context, \func_num_args() > 1 ? func_get_arg(1) : []); } /** @@ -61,7 +67,7 @@ final class Twig_TemplateWrapper * * @return bool */ - public function hasBlock($name, $context = array()) + public function hasBlock($name, $context = []) { return $this->template->hasBlock($name, $context); } @@ -73,7 +79,7 @@ final class Twig_TemplateWrapper * * @return string[] An array of defined template block names */ - public function getBlockNames($context = array()) + public function getBlockNames($context = []) { return $this->template->getBlockNames($context); } @@ -86,20 +92,24 @@ final class Twig_TemplateWrapper * * @return string The rendered block */ - public function renderBlock($name, $context = array()) + public function renderBlock($name, $context = []) { $context = $this->env->mergeGlobals($context); $level = ob_get_level(); - ob_start(); + if ($this->env->isDebug()) { + ob_start(); + } else { + ob_start(function () { return ''; }); + } try { $this->template->displayBlock($name, $context); - } catch (Exception $e) { + } catch (\Exception $e) { while (ob_get_level() > $level) { ob_end_clean(); } throw $e; - } catch (Throwable $e) { + } catch (\Throwable $e) { while (ob_get_level() > $level) { ob_end_clean(); } @@ -116,18 +126,36 @@ final class Twig_TemplateWrapper * @param string $name The block name to render * @param array $context An array of parameters to pass to the template */ - public function displayBlock($name, $context = array()) + public function displayBlock($name, $context = []) { $this->template->displayBlock($name, $this->env->mergeGlobals($context)); } /** - * @return Twig_Source + * @return Source */ public function getSourceContext() { return $this->template->getSourceContext(); } + + /** + * @return string + */ + public function getTemplateName() + { + return $this->template->getTemplateName(); + } + + /** + * @internal + * + * @return Template + */ + public function unwrap() + { + return $this->template; + } } -class_alias('Twig_TemplateWrapper', 'Twig\TemplateWrapper', false); +class_alias('Twig\TemplateWrapper', 'Twig_TemplateWrapper'); diff --git a/system/libs/Twig/Test/IntegrationTestCase.php b/system/libs/Twig/Test/IntegrationTestCase.php index 016951aa..36b36075 100755 --- a/system/libs/Twig/Test/IntegrationTestCase.php +++ b/system/libs/Twig/Test/IntegrationTestCase.php @@ -9,7 +9,19 @@ * file that was distributed with this source code. */ +namespace Twig\Test; + use PHPUnit\Framework\TestCase; +use Twig\Environment; +use Twig\Error\Error; +use Twig\Extension\ExtensionInterface; +use Twig\Loader\ArrayLoader; +use Twig\Loader\SourceContextLoaderInterface; +use Twig\RuntimeLoader\RuntimeLoaderInterface; +use Twig\Source; +use Twig\TwigFilter; +use Twig\TwigFunction; +use Twig\TwigTest; /** * Integration test helper. @@ -17,7 +29,7 @@ use PHPUnit\Framework\TestCase; * @author Fabien Potencier * @author Karma Dordrak */ -abstract class Twig_Test_IntegrationTestCase extends TestCase +abstract class IntegrationTestCase extends TestCase { /** * @return string @@ -25,43 +37,43 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase abstract protected function getFixturesDir(); /** - * @return Twig_RuntimeLoaderInterface[] + * @return RuntimeLoaderInterface[] */ protected function getRuntimeLoaders() { - return array(); + return []; } /** - * @return Twig_ExtensionInterface[] + * @return ExtensionInterface[] */ protected function getExtensions() { - return array(); + return []; } /** - * @return Twig_SimpleFilter[] + * @return TwigFilter[] */ protected function getTwigFilters() { - return array(); + return []; } /** - * @return Twig_SimpleFunction[] + * @return TwigFunction[] */ protected function getTwigFunctions() { - return array(); + return []; } /** - * @return Twig_SimpleTest[] + * @return TwigTest[] */ protected function getTwigTests() { - return array(); + return []; } /** @@ -84,9 +96,9 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase public function getTests($name, $legacyTests = false) { $fixturesDir = realpath($this->getFixturesDir()); - $tests = array(); + $tests = []; - foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($fixturesDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file) { + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($fixturesDir), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { if (!preg_match('/\.test$/', $file)) { continue; } @@ -102,7 +114,7 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase $condition = $match[2]; $templates = self::parseTemplates($match[3]); $exception = $match[5]; - $outputs = array(array(null, $match[4], null, '')); + $outputs = [[null, $match[4], null, '']]; } elseif (preg_match('/--TEST--\s*(.*?)\s*(?:--CONDITION--\s*(.*))?\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)--DATA--.*?--EXPECT--.*/s', $test, $match)) { $message = $match[1]; $condition = $match[2]; @@ -110,15 +122,15 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase $exception = false; preg_match_all('/--DATA--(.*?)(?:--CONFIG--(.*?))?--EXPECT--(.*?)(?=\-\-DATA\-\-|$)/s', $test, $outputs, PREG_SET_ORDER); } else { - throw new InvalidArgumentException(sprintf('Test "%s" is not valid.', str_replace($fixturesDir.'/', '', $file))); + throw new \InvalidArgumentException(sprintf('Test "%s" is not valid.', str_replace($fixturesDir.'/', '', $file))); } - $tests[] = array(str_replace($fixturesDir.'/', '', $file), $message, $condition, $templates, $exception, $outputs); + $tests[] = [str_replace($fixturesDir.'/', '', $file), $message, $condition, $templates, $exception, $outputs]; } if ($legacyTests && empty($tests)) { // add a dummy test to avoid a PHPUnit message - return array(array('not', '-', '', array(), '', array())); + return [['not', '-', '', [], '', []]]; } return $tests; @@ -132,7 +144,7 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase protected function doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs) { if (!$outputs) { - $this->markTestSkipped('no legacy tests to run'); + $this->markTestSkipped('no tests to run'); } if ($condition) { @@ -142,14 +154,14 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase } } - $loader = new Twig_Loader_Array($templates); + $loader = new ArrayLoader($templates); foreach ($outputs as $i => $match) { - $config = array_merge(array( + $config = array_merge([ 'cache' => false, 'strict_variables' => true, - ), $match[2] ? eval($match[2].';') : array()); - $twig = new Twig_Environment($loader, $config); + ], $match[2] ? eval($match[2].';') : []); + $twig = new Environment($loader, $config); $twig->addGlobal('global', 'global'); foreach ($this->getRuntimeLoaders() as $runtimeLoader) { $twig->addRuntimeLoader($runtimeLoader); @@ -171,41 +183,37 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase $twig->addFunction($function); } - // avoid using the same PHP class name for different cases - // only for PHP 5.2+ - if (PHP_VERSION_ID >= 50300) { - $p = new ReflectionProperty($twig, 'templateClassPrefix'); - $p->setAccessible(true); - $p->setValue($twig, '__TwigTemplate_'.hash('sha256', uniqid(mt_rand(), true), false).'_'); - } + $p = new \ReflectionProperty($twig, 'templateClassPrefix'); + $p->setAccessible(true); + $p->setValue($twig, '__TwigTemplate_'.hash('sha256', uniqid(mt_rand(), true), false).'_'); try { - $template = $twig->loadTemplate('index.twig'); - } catch (Exception $e) { + $template = $twig->load('index.twig'); + } catch (\Exception $e) { if (false !== $exception) { $message = $e->getMessage(); - $this->assertSame(trim($exception), trim(sprintf('%s: %s', get_class($e), $message))); - $last = substr($message, strlen($message) - 1); - $this->assertTrue('.' === $last || '?' === $last, $message, 'Exception message must end with a dot or a question mark.'); + $this->assertSame(trim($exception), trim(sprintf('%s: %s', \get_class($e), $message))); + $last = substr($message, \strlen($message) - 1); + $this->assertTrue('.' === $last || '?' === $last, 'Exception message must end with a dot or a question mark.'); return; } - throw new Twig_Error(sprintf('%s: %s', get_class($e), $e->getMessage()), -1, $file, $e); + throw new Error(sprintf('%s: %s', \get_class($e), $e->getMessage()), -1, null, $e); } try { $output = trim($template->render(eval($match[1].';')), "\n "); - } catch (Exception $e) { + } catch (\Exception $e) { if (false !== $exception) { - $this->assertSame(trim($exception), trim(sprintf('%s: %s', get_class($e), $e->getMessage()))); + $this->assertSame(trim($exception), trim(sprintf('%s: %s', \get_class($e), $e->getMessage()))); return; } - $e = new Twig_Error(sprintf('%s: %s', get_class($e), $e->getMessage()), -1, $file, $e); + $e = new Error(sprintf('%s: %s', \get_class($e), $e->getMessage()), -1, null, $e); - $output = trim(sprintf('%s: %s', get_class($e), $e->getMessage())); + $output = trim(sprintf('%s: %s', \get_class($e), $e->getMessage())); } if (false !== $exception) { @@ -222,8 +230,8 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase foreach (array_keys($templates) as $name) { echo "Template: $name\n"; $loader = $twig->getLoader(); - if (!$loader instanceof Twig_SourceContextLoaderInterface) { - $source = new Twig_Source($loader->getSource($name), $name); + if (!$loader instanceof SourceContextLoaderInterface) { + $source = new Source($loader->getSource($name), $name); } else { $source = $loader->getSourceContext($name); } @@ -236,7 +244,7 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase protected static function parseTemplates($test) { - $templates = array(); + $templates = []; preg_match_all('/--TEMPLATE(?:\((.*?)\))?--(.*?)(?=\-\-TEMPLATE|$)/s', $test, $matches, PREG_SET_ORDER); foreach ($matches as $match) { $templates[($match[1] ? $match[1] : 'index.twig')] = $match[2]; @@ -246,4 +254,4 @@ abstract class Twig_Test_IntegrationTestCase extends TestCase } } -class_alias('Twig_Test_IntegrationTestCase', 'Twig\Test\IntegrationTestCase', false); +class_alias('Twig\Test\IntegrationTestCase', 'Twig_Test_IntegrationTestCase'); diff --git a/system/libs/Twig/Test/NodeTestCase.php b/system/libs/Twig/Test/NodeTestCase.php index 47942675..f3358cb9 100755 --- a/system/libs/Twig/Test/NodeTestCase.php +++ b/system/libs/Twig/Test/NodeTestCase.php @@ -9,9 +9,15 @@ * file that was distributed with this source code. */ -use PHPUnit\Framework\TestCase; +namespace Twig\Test; -abstract class Twig_Test_NodeTestCase extends TestCase +use PHPUnit\Framework\TestCase; +use Twig\Compiler; +use Twig\Environment; +use Twig\Loader\ArrayLoader; +use Twig\Node\Node; + +abstract class NodeTestCase extends TestCase { abstract public function getTests(); @@ -23,7 +29,7 @@ abstract class Twig_Test_NodeTestCase extends TestCase $this->assertNodeCompilation($source, $node, $environment, $isPattern); } - public function assertNodeCompilation($source, Twig_Node $node, Twig_Environment $environment = null, $isPattern = false) + public function assertNodeCompilation($source, Node $node, Environment $environment = null, $isPattern = false) { $compiler = $this->getCompiler($environment); $compiler->compile($node); @@ -35,25 +41,25 @@ abstract class Twig_Test_NodeTestCase extends TestCase } } - protected function getCompiler(Twig_Environment $environment = null) + protected function getCompiler(Environment $environment = null) { - return new Twig_Compiler(null === $environment ? $this->getEnvironment() : $environment); + return new Compiler(null === $environment ? $this->getEnvironment() : $environment); } protected function getEnvironment() { - return new Twig_Environment(new Twig_Loader_Array(array())); + return new Environment(new ArrayLoader([])); } protected function getVariableGetter($name, $line = false) { $line = $line > 0 ? "// line {$line}\n" : ''; - if (PHP_VERSION_ID >= 70000) { - return sprintf('%s($context["%s"] ?? null)', $line, $name, $name); + if (\PHP_VERSION_ID >= 70000) { + return sprintf('%s($context["%s"] ?? null)', $line, $name); } - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { return sprintf('%s(isset($context["%s"]) ? $context["%s"] : null)', $line, $name, $name); } @@ -62,7 +68,7 @@ abstract class Twig_Test_NodeTestCase extends TestCase protected function getAttributeGetter() { - if (function_exists('twig_template_get_attributes')) { + if (\function_exists('twig_template_get_attributes')) { return 'twig_template_get_attributes($this, '; } @@ -70,6 +76,4 @@ abstract class Twig_Test_NodeTestCase extends TestCase } } -class_alias('Twig_Test_NodeTestCase', 'Twig\Test\NodeTestCase', false); -class_exists('Twig_Environment'); -class_exists('Twig_Node'); +class_alias('Twig\Test\NodeTestCase', 'Twig_Test_NodeTestCase'); diff --git a/system/libs/Twig/Token.php b/system/libs/Twig/Token.php index c7850ecc..a0bb11af 100755 --- a/system/libs/Twig/Token.php +++ b/system/libs/Twig/Token.php @@ -10,6 +10,8 @@ * file that was distributed with this source code. */ +namespace Twig; + /** * Represents a Token. * @@ -17,7 +19,7 @@ * * @final */ -class Twig_Token +class Token { protected $value; protected $type; @@ -36,6 +38,7 @@ class Twig_Token const PUNCTUATION_TYPE = 9; const INTERPOLATION_START_TYPE = 10; const INTERPOLATION_END_TYPE = 11; + const ARROW_TYPE = 12; /** * @param int $type The type of the token @@ -62,21 +65,21 @@ class Twig_Token * * type and value (or array of possible values) * * just value (or array of possible values) (NAME_TYPE is used as type) * - * @param array|int $type The type to test + * @param array|string|int $type The type to test * @param array|string|null $values The token value * * @return bool */ public function test($type, $values = null) { - if (null === $values && !is_int($type)) { + if (null === $values && !\is_int($type)) { $values = $type; $type = self::NAME_TYPE; } return ($this->type === $type) && ( null === $values || - (is_array($values) && in_array($this->value, $values)) || + (\is_array($values) && \in_array($this->value, $values)) || $this->value == $values ); } @@ -155,11 +158,14 @@ class Twig_Token case self::INTERPOLATION_END_TYPE: $name = 'INTERPOLATION_END_TYPE'; break; + case self::ARROW_TYPE: + $name = 'ARROW_TYPE'; + break; default: - throw new LogicException(sprintf('Token of type "%s" does not exist.', $type)); + throw new \LogicException(sprintf('Token of type "%s" does not exist.', $type)); } - return $short ? $name : 'Twig_Token::'.$name; + return $short ? $name : 'Twig\Token::'.$name; } /** @@ -198,10 +204,12 @@ class Twig_Token return 'begin of string interpolation'; case self::INTERPOLATION_END_TYPE: return 'end of string interpolation'; + case self::ARROW_TYPE: + return 'arrow function'; default: - throw new LogicException(sprintf('Token of type "%s" does not exist.', $type)); + throw new \LogicException(sprintf('Token of type "%s" does not exist.', $type)); } } } -class_alias('Twig_Token', 'Twig\Token', false); +class_alias('Twig\Token', 'Twig_Token'); diff --git a/system/libs/Twig/TokenParser.php b/system/libs/Twig/TokenParser/AbstractTokenParser.php old mode 100755 new mode 100644 similarity index 56% rename from system/libs/Twig/TokenParser.php rename to system/libs/Twig/TokenParser/AbstractTokenParser.php index 1b4de14d..2c2f90b7 --- a/system/libs/Twig/TokenParser.php +++ b/system/libs/Twig/TokenParser/AbstractTokenParser.php @@ -9,25 +9,26 @@ * file that was distributed with this source code. */ +namespace Twig\TokenParser; + +use Twig\Parser; + /** * Base class for all token parsers. * * @author Fabien Potencier */ -abstract class Twig_TokenParser implements Twig_TokenParserInterface +abstract class AbstractTokenParser implements TokenParserInterface { /** - * @var Twig_Parser + * @var Parser */ protected $parser; - /** - * Sets the parser associated with this token parser. - */ - public function setParser(Twig_Parser $parser) + public function setParser(Parser $parser) { $this->parser = $parser; } } -class_alias('Twig_TokenParser', 'Twig\TokenParser\AbstractTokenParser', false); +class_alias('Twig\TokenParser\AbstractTokenParser', 'Twig_TokenParser'); diff --git a/system/libs/Twig/TokenParser/ApplyTokenParser.php b/system/libs/Twig/TokenParser/ApplyTokenParser.php new file mode 100644 index 00000000..879879a2 --- /dev/null +++ b/system/libs/Twig/TokenParser/ApplyTokenParser.php @@ -0,0 +1,58 @@ +getLine(); + $name = $this->parser->getVarName(); + + $ref = new TempNameExpression($name, $lineno); + $ref->setAttribute('always_defined', true); + + $filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag()); + + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + $body = $this->parser->subparse([$this, 'decideApplyEnd'], true); + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + + return new Node([ + new SetNode(true, $ref, $body, $lineno, $this->getTag()), + new PrintNode($filter, $lineno, $this->getTag()), + ]); + } + + public function decideApplyEnd(Token $token) + { + return $token->test('endapply'); + } + + public function getTag() + { + return 'apply'; + } +} diff --git a/system/libs/Twig/TokenParser/AutoEscape.php b/system/libs/Twig/TokenParser/AutoEscape.php deleted file mode 100755 index a20dedd1..00000000 --- a/system/libs/Twig/TokenParser/AutoEscape.php +++ /dev/null @@ -1,83 +0,0 @@ - - * {% autoescape true %} - * Everything will be automatically escaped in this block - * {% endautoescape %} - * - * {% autoescape false %} - * Everything will be outputed as is in this block - * {% endautoescape %} - * - * {% autoescape true js %} - * Everything will be automatically escaped in this block - * using the js escaping strategy - * {% endautoescape %} - * - * - * @final - */ -class Twig_TokenParser_AutoEscape extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - - if ($stream->test(Twig_Token::BLOCK_END_TYPE)) { - $value = 'html'; - } else { - $expr = $this->parser->getExpressionParser()->parseExpression(); - if (!$expr instanceof Twig_Node_Expression_Constant) { - throw new Twig_Error_Syntax('An escaping strategy must be a string or a bool.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - $value = $expr->getAttribute('value'); - - $compat = true === $value || false === $value; - - if (true === $value) { - $value = 'html'; - } - - if ($compat && $stream->test(Twig_Token::NAME_TYPE)) { - @trigger_error('Using the autoescape tag with "true" or "false" before the strategy name is deprecated since version 1.21.', E_USER_DEPRECATED); - - if (false === $value) { - throw new Twig_Error_Syntax('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - - $value = $stream->next()->getValue(); - } - } - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - return new Twig_Node_AutoEscape($value, $body, $lineno, $this->getTag()); - } - - public function decideBlockEnd(Twig_Token $token) - { - return $token->test('endautoescape'); - } - - public function getTag() - { - return 'autoescape'; - } -} - -class_alias('Twig_TokenParser_AutoEscape', 'Twig\TokenParser\AutoEscapeTokenParser', false); diff --git a/system/libs/Twig/TokenParser/AutoEscapeTokenParser.php b/system/libs/Twig/TokenParser/AutoEscapeTokenParser.php new file mode 100644 index 00000000..2cd0cc69 --- /dev/null +++ b/system/libs/Twig/TokenParser/AutoEscapeTokenParser.php @@ -0,0 +1,88 @@ +getLine(); + $stream = $this->parser->getStream(); + + if ($stream->test(Token::BLOCK_END_TYPE)) { + $value = 'html'; + } else { + $expr = $this->parser->getExpressionParser()->parseExpression(); + if (!$expr instanceof ConstantExpression) { + throw new SyntaxError('An escaping strategy must be a string or a bool.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + $value = $expr->getAttribute('value'); + + $compat = true === $value || false === $value; + + if (true === $value) { + $value = 'html'; + } + + if ($compat && $stream->test(Token::NAME_TYPE)) { + @trigger_error('Using the autoescape tag with "true" or "false" before the strategy name is deprecated since version 1.21.', E_USER_DEPRECATED); + + if (false === $value) { + throw new SyntaxError('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + + $value = $stream->next()->getValue(); + } + } + + $stream->expect(Token::BLOCK_END_TYPE); + $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); + $stream->expect(Token::BLOCK_END_TYPE); + + return new AutoEscapeNode($value, $body, $lineno, $this->getTag()); + } + + public function decideBlockEnd(Token $token) + { + return $token->test('endautoescape'); + } + + public function getTag() + { + return 'autoescape'; + } +} + +class_alias('Twig\TokenParser\AutoEscapeTokenParser', 'Twig_TokenParser_AutoEscape'); diff --git a/system/libs/Twig/TokenParser/Block.php b/system/libs/Twig/TokenParser/Block.php deleted file mode 100755 index f30f86b5..00000000 --- a/system/libs/Twig/TokenParser/Block.php +++ /dev/null @@ -1,73 +0,0 @@ - - * {% block head %} - * - * {% block title %}{% endblock %} - My Webpage - * {% endblock %} - * - * - * @final - */ -class Twig_TokenParser_Block extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); - if ($this->parser->hasBlock($name)) { - throw new Twig_Error_Syntax(sprintf("The block '%s' has already been defined line %d.", $name, $this->parser->getBlock($name)->getTemplateLine()), $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - $this->parser->setBlock($name, $block = new Twig_Node_Block($name, new Twig_Node(array()), $lineno)); - $this->parser->pushLocalScope(); - $this->parser->pushBlockStack($name); - - if ($stream->nextIf(Twig_Token::BLOCK_END_TYPE)) { - $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - if ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) { - $value = $token->getValue(); - - if ($value != $name) { - throw new Twig_Error_Syntax(sprintf('Expected endblock for block "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - } - } else { - $body = new Twig_Node(array( - new Twig_Node_Print($this->parser->getExpressionParser()->parseExpression(), $lineno), - )); - } - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - $block->setNode('body', $body); - $this->parser->popBlockStack(); - $this->parser->popLocalScope(); - - return new Twig_Node_BlockReference($name, $lineno, $this->getTag()); - } - - public function decideBlockEnd(Twig_Token $token) - { - return $token->test('endblock'); - } - - public function getTag() - { - return 'block'; - } -} - -class_alias('Twig_TokenParser_Block', 'Twig\TokenParser\BlockTokenParser', false); diff --git a/system/libs/Twig/TokenParser/BlockTokenParser.php b/system/libs/Twig/TokenParser/BlockTokenParser.php new file mode 100644 index 00000000..caf11f0b --- /dev/null +++ b/system/libs/Twig/TokenParser/BlockTokenParser.php @@ -0,0 +1,80 @@ + + * {% block title %}{% endblock %} - My Webpage + * {% endblock %} + * + * @final + */ +class BlockTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + $name = $stream->expect(Token::NAME_TYPE)->getValue(); + if ($this->parser->hasBlock($name)) { + throw new SyntaxError(sprintf("The block '%s' has already been defined line %d.", $name, $this->parser->getBlock($name)->getTemplateLine()), $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + $this->parser->setBlock($name, $block = new BlockNode($name, new Node([]), $lineno)); + $this->parser->pushLocalScope(); + $this->parser->pushBlockStack($name); + + if ($stream->nextIf(Token::BLOCK_END_TYPE)) { + $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); + if ($token = $stream->nextIf(Token::NAME_TYPE)) { + $value = $token->getValue(); + + if ($value != $name) { + throw new SyntaxError(sprintf('Expected endblock for block "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + } + } else { + $body = new Node([ + new PrintNode($this->parser->getExpressionParser()->parseExpression(), $lineno), + ]); + } + $stream->expect(Token::BLOCK_END_TYPE); + + $block->setNode('body', $body); + $this->parser->popBlockStack(); + $this->parser->popLocalScope(); + + return new BlockReferenceNode($name, $lineno, $this->getTag()); + } + + public function decideBlockEnd(Token $token) + { + return $token->test('endblock'); + } + + public function getTag() + { + return 'block'; + } +} + +class_alias('Twig\TokenParser\BlockTokenParser', 'Twig_TokenParser_Block'); diff --git a/system/libs/Twig/TokenParser/DeprecatedTokenParser.php b/system/libs/Twig/TokenParser/DeprecatedTokenParser.php new file mode 100644 index 00000000..6575cff1 --- /dev/null +++ b/system/libs/Twig/TokenParser/DeprecatedTokenParser.php @@ -0,0 +1,44 @@ + + * + * @final + */ +class DeprecatedTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $expr = $this->parser->getExpressionParser()->parseExpression(); + + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + + return new DeprecatedNode($expr, $token->getLine(), $this->getTag()); + } + + public function getTag() + { + return 'deprecated'; + } +} + +class_alias('Twig\TokenParser\DeprecatedTokenParser', 'Twig_TokenParser_Deprecated'); diff --git a/system/libs/Twig/TokenParser/Do.php b/system/libs/Twig/TokenParser/DoTokenParser.php old mode 100755 new mode 100644 similarity index 54% rename from system/libs/Twig/TokenParser/Do.php rename to system/libs/Twig/TokenParser/DoTokenParser.php index 8ce08808..e1eae10f --- a/system/libs/Twig/TokenParser/Do.php +++ b/system/libs/Twig/TokenParser/DoTokenParser.php @@ -9,20 +9,25 @@ * file that was distributed with this source code. */ +namespace Twig\TokenParser; + +use Twig\Node\DoNode; +use Twig\Token; + /** * Evaluates an expression, discarding the returned value. * * @final */ -class Twig_TokenParser_Do extends Twig_TokenParser +class DoTokenParser extends AbstractTokenParser { - public function parse(Twig_Token $token) + public function parse(Token $token) { $expr = $this->parser->getExpressionParser()->parseExpression(); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); - return new Twig_Node_Do($expr, $token->getLine(), $this->getTag()); + return new DoNode($expr, $token->getLine(), $this->getTag()); } public function getTag() @@ -31,4 +36,4 @@ class Twig_TokenParser_Do extends Twig_TokenParser } } -class_alias('Twig_TokenParser_Do', 'Twig\TokenParser\DoTokenParser', false); +class_alias('Twig\TokenParser\DoTokenParser', 'Twig_TokenParser_Do'); diff --git a/system/libs/Twig/TokenParser/Embed.php b/system/libs/Twig/TokenParser/Embed.php deleted file mode 100755 index 44644cc6..00000000 --- a/system/libs/Twig/TokenParser/Embed.php +++ /dev/null @@ -1,67 +0,0 @@ -parser->getStream(); - - $parent = $this->parser->getExpressionParser()->parseExpression(); - - list($variables, $only, $ignoreMissing) = $this->parseArguments(); - - $parentToken = $fakeParentToken = new Twig_Token(Twig_Token::STRING_TYPE, '__parent__', $token->getLine()); - if ($parent instanceof Twig_Node_Expression_Constant) { - $parentToken = new Twig_Token(Twig_Token::STRING_TYPE, $parent->getAttribute('value'), $token->getLine()); - } elseif ($parent instanceof Twig_Node_Expression_Name) { - $parentToken = new Twig_Token(Twig_Token::NAME_TYPE, $parent->getAttribute('name'), $token->getLine()); - } - - // inject a fake parent to make the parent() function work - $stream->injectTokens(array( - new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', $token->getLine()), - new Twig_Token(Twig_Token::NAME_TYPE, 'extends', $token->getLine()), - $parentToken, - new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', $token->getLine()), - )); - - $module = $this->parser->parse($stream, array($this, 'decideBlockEnd'), true); - - // override the parent with the correct one - if ($fakeParentToken === $parentToken) { - $module->setNode('parent', $parent); - } - - $this->parser->embedTemplate($module); - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - return new Twig_Node_Embed($module->getTemplateName(), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); - } - - public function decideBlockEnd(Twig_Token $token) - { - return $token->test('endembed'); - } - - public function getTag() - { - return 'embed'; - } -} - -class_alias('Twig_TokenParser_Embed', 'Twig\TokenParser\EmbedTokenParser', false); diff --git a/system/libs/Twig/TokenParser/EmbedTokenParser.php b/system/libs/Twig/TokenParser/EmbedTokenParser.php new file mode 100644 index 00000000..973ff2e4 --- /dev/null +++ b/system/libs/Twig/TokenParser/EmbedTokenParser.php @@ -0,0 +1,74 @@ +parser->getStream(); + + $parent = $this->parser->getExpressionParser()->parseExpression(); + + list($variables, $only, $ignoreMissing) = $this->parseArguments(); + + $parentToken = $fakeParentToken = new Token(Token::STRING_TYPE, '__parent__', $token->getLine()); + if ($parent instanceof ConstantExpression) { + $parentToken = new Token(Token::STRING_TYPE, $parent->getAttribute('value'), $token->getLine()); + } elseif ($parent instanceof NameExpression) { + $parentToken = new Token(Token::NAME_TYPE, $parent->getAttribute('name'), $token->getLine()); + } + + // inject a fake parent to make the parent() function work + $stream->injectTokens([ + new Token(Token::BLOCK_START_TYPE, '', $token->getLine()), + new Token(Token::NAME_TYPE, 'extends', $token->getLine()), + $parentToken, + new Token(Token::BLOCK_END_TYPE, '', $token->getLine()), + ]); + + $module = $this->parser->parse($stream, [$this, 'decideBlockEnd'], true); + + // override the parent with the correct one + if ($fakeParentToken === $parentToken) { + $module->setNode('parent', $parent); + } + + $this->parser->embedTemplate($module); + + $stream->expect(Token::BLOCK_END_TYPE); + + return new EmbedNode($module->getTemplateName(), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); + } + + public function decideBlockEnd(Token $token) + { + return $token->test('endembed'); + } + + public function getTag() + { + return 'embed'; + } +} + +class_alias('Twig\TokenParser\EmbedTokenParser', 'Twig_TokenParser_Embed'); diff --git a/system/libs/Twig/TokenParser/Extends.php b/system/libs/Twig/TokenParser/Extends.php deleted file mode 100755 index 31168cce..00000000 --- a/system/libs/Twig/TokenParser/Extends.php +++ /dev/null @@ -1,46 +0,0 @@ - - * {% extends "base.html" %} - * - * - * @final - */ -class Twig_TokenParser_Extends extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $stream = $this->parser->getStream(); - - if (!$this->parser->isMainScope()) { - throw new Twig_Error_Syntax('Cannot extend from a block.', $token->getLine(), $stream->getSourceContext()); - } - - if (null !== $this->parser->getParent()) { - throw new Twig_Error_Syntax('Multiple extends tags are forbidden.', $token->getLine(), $stream->getSourceContext()); - } - $this->parser->setParent($this->parser->getExpressionParser()->parseExpression()); - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - } - - public function getTag() - { - return 'extends'; - } -} - -class_alias('Twig_TokenParser_Extends', 'Twig\TokenParser\ExtendsTokenParser', false); diff --git a/system/libs/Twig/TokenParser/ExtendsTokenParser.php b/system/libs/Twig/TokenParser/ExtendsTokenParser.php new file mode 100644 index 00000000..e66789a7 --- /dev/null +++ b/system/libs/Twig/TokenParser/ExtendsTokenParser.php @@ -0,0 +1,54 @@ +parser->getStream(); + + if ($this->parser->peekBlockStack()) { + throw new SyntaxError('Cannot use "extend" in a block.', $token->getLine(), $stream->getSourceContext()); + } elseif (!$this->parser->isMainScope()) { + throw new SyntaxError('Cannot use "extend" in a macro.', $token->getLine(), $stream->getSourceContext()); + } + + if (null !== $this->parser->getParent()) { + throw new SyntaxError('Multiple extends tags are forbidden.', $token->getLine(), $stream->getSourceContext()); + } + $this->parser->setParent($this->parser->getExpressionParser()->parseExpression()); + + $stream->expect(Token::BLOCK_END_TYPE); + + return new Node(); + } + + public function getTag() + { + return 'extends'; + } +} + +class_alias('Twig\TokenParser\ExtendsTokenParser', 'Twig_TokenParser_Extends'); diff --git a/system/libs/Twig/TokenParser/Filter.php b/system/libs/Twig/TokenParser/Filter.php deleted file mode 100755 index 76017829..00000000 --- a/system/libs/Twig/TokenParser/Filter.php +++ /dev/null @@ -1,53 +0,0 @@ - - * {% filter upper %} - * This text becomes uppercase - * {% endfilter %} - * - * - * @final - */ -class Twig_TokenParser_Filter extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $name = $this->parser->getVarName(); - $ref = new Twig_Node_Expression_BlockReference(new Twig_Node_Expression_Constant($name, $token->getLine()), null, $token->getLine(), $this->getTag()); - - $filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag()); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - - $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - - $block = new Twig_Node_Block($name, $body, $token->getLine()); - $this->parser->setBlock($name, $block); - - return new Twig_Node_Print($filter, $token->getLine(), $this->getTag()); - } - - public function decideBlockEnd(Twig_Token $token) - { - return $token->test('endfilter'); - } - - public function getTag() - { - return 'filter'; - } -} - -class_alias('Twig_TokenParser_Filter', 'Twig\TokenParser\FilterTokenParser', false); diff --git a/system/libs/Twig/TokenParser/FilterTokenParser.php b/system/libs/Twig/TokenParser/FilterTokenParser.php new file mode 100644 index 00000000..dc07dcfa --- /dev/null +++ b/system/libs/Twig/TokenParser/FilterTokenParser.php @@ -0,0 +1,59 @@ +parser->getVarName(); + $ref = new BlockReferenceExpression(new ConstantExpression($name, $token->getLine()), null, $token->getLine(), $this->getTag()); + + $filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag()); + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + + $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + + $block = new BlockNode($name, $body, $token->getLine()); + $this->parser->setBlock($name, $block); + + return new PrintNode($filter, $token->getLine(), $this->getTag()); + } + + public function decideBlockEnd(Token $token) + { + return $token->test('endfilter'); + } + + public function getTag() + { + return 'filter'; + } +} + +class_alias('Twig\TokenParser\FilterTokenParser', 'Twig_TokenParser_Filter'); diff --git a/system/libs/Twig/TokenParser/Flush.php b/system/libs/Twig/TokenParser/Flush.php deleted file mode 100755 index 51832c77..00000000 --- a/system/libs/Twig/TokenParser/Flush.php +++ /dev/null @@ -1,34 +0,0 @@ -parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - - return new Twig_Node_Flush($token->getLine(), $this->getTag()); - } - - public function getTag() - { - return 'flush'; - } -} - -class_alias('Twig_TokenParser_Flush', 'Twig\TokenParser\FlushTokenParser', false); diff --git a/system/libs/Twig/TokenParser/FlushTokenParser.php b/system/libs/Twig/TokenParser/FlushTokenParser.php new file mode 100644 index 00000000..b25524fa --- /dev/null +++ b/system/libs/Twig/TokenParser/FlushTokenParser.php @@ -0,0 +1,39 @@ +parser->getStream()->expect(Token::BLOCK_END_TYPE); + + return new FlushNode($token->getLine(), $this->getTag()); + } + + public function getTag() + { + return 'flush'; + } +} + +class_alias('Twig\TokenParser\FlushTokenParser', 'Twig_TokenParser_Flush'); diff --git a/system/libs/Twig/TokenParser/For.php b/system/libs/Twig/TokenParser/For.php deleted file mode 100755 index 63bf41d6..00000000 --- a/system/libs/Twig/TokenParser/For.php +++ /dev/null @@ -1,127 +0,0 @@ - - *
    - * {% for user in users %} - *
  • {{ user.username|e }}
  • - * {% endfor %} - *
- * - * - * @final - */ -class Twig_TokenParser_For extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - $targets = $this->parser->getExpressionParser()->parseAssignmentExpression(); - $stream->expect(Twig_Token::OPERATOR_TYPE, 'in'); - $seq = $this->parser->getExpressionParser()->parseExpression(); - - $ifexpr = null; - if ($stream->nextIf(Twig_Token::NAME_TYPE, 'if')) { - $ifexpr = $this->parser->getExpressionParser()->parseExpression(); - } - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideForFork')); - if ($stream->next()->getValue() == 'else') { - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $else = $this->parser->subparse(array($this, 'decideForEnd'), true); - } else { - $else = null; - } - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - if (count($targets) > 1) { - $keyTarget = $targets->getNode(0); - $keyTarget = new Twig_Node_Expression_AssignName($keyTarget->getAttribute('name'), $keyTarget->getTemplateLine()); - $valueTarget = $targets->getNode(1); - $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine()); - } else { - $keyTarget = new Twig_Node_Expression_AssignName('_key', $lineno); - $valueTarget = $targets->getNode(0); - $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine()); - } - - if ($ifexpr) { - $this->checkLoopUsageCondition($stream, $ifexpr); - $this->checkLoopUsageBody($stream, $body); - } - - return new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, $lineno, $this->getTag()); - } - - public function decideForFork(Twig_Token $token) - { - return $token->test(array('else', 'endfor')); - } - - public function decideForEnd(Twig_Token $token) - { - return $token->test('endfor'); - } - - // the loop variable cannot be used in the condition - protected function checkLoopUsageCondition(Twig_TokenStream $stream, Twig_NodeInterface $node) - { - if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) { - throw new Twig_Error_Syntax('The "loop" variable cannot be used in a looping condition.', $node->getTemplateLine(), $stream->getSourceContext()); - } - - foreach ($node as $n) { - if (!$n) { - continue; - } - - $this->checkLoopUsageCondition($stream, $n); - } - } - - // check usage of non-defined loop-items - // it does not catch all problems (for instance when a for is included into another or when the variable is used in an include) - protected function checkLoopUsageBody(Twig_TokenStream $stream, Twig_NodeInterface $node) - { - if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) { - $attribute = $node->getNode('attribute'); - if ($attribute instanceof Twig_Node_Expression_Constant && in_array($attribute->getAttribute('value'), array('length', 'revindex0', 'revindex', 'last'))) { - throw new Twig_Error_Syntax(sprintf('The "loop.%s" variable is not defined when looping with a condition.', $attribute->getAttribute('value')), $node->getTemplateLine(), $stream->getSourceContext()); - } - } - - // should check for parent.loop.XXX usage - if ($node instanceof Twig_Node_For) { - return; - } - - foreach ($node as $n) { - if (!$n) { - continue; - } - - $this->checkLoopUsageBody($stream, $n); - } - } - - public function getTag() - { - return 'for'; - } -} - -class_alias('Twig_TokenParser_For', 'Twig\TokenParser\ForTokenParser', false); diff --git a/system/libs/Twig/TokenParser/ForTokenParser.php b/system/libs/Twig/TokenParser/ForTokenParser.php new file mode 100644 index 00000000..69278d98 --- /dev/null +++ b/system/libs/Twig/TokenParser/ForTokenParser.php @@ -0,0 +1,136 @@ + + * {% for user in users %} + *
  • {{ user.username|e }}
  • + * {% endfor %} + * + * + * @final + */ +class ForTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + $targets = $this->parser->getExpressionParser()->parseAssignmentExpression(); + $stream->expect(Token::OPERATOR_TYPE, 'in'); + $seq = $this->parser->getExpressionParser()->parseExpression(); + + $ifexpr = null; + if ($stream->nextIf(Token::NAME_TYPE, 'if')) { + $ifexpr = $this->parser->getExpressionParser()->parseExpression(); + } + + $stream->expect(Token::BLOCK_END_TYPE); + $body = $this->parser->subparse([$this, 'decideForFork']); + if ('else' == $stream->next()->getValue()) { + $stream->expect(Token::BLOCK_END_TYPE); + $else = $this->parser->subparse([$this, 'decideForEnd'], true); + } else { + $else = null; + } + $stream->expect(Token::BLOCK_END_TYPE); + + if (\count($targets) > 1) { + $keyTarget = $targets->getNode(0); + $keyTarget = new AssignNameExpression($keyTarget->getAttribute('name'), $keyTarget->getTemplateLine()); + $valueTarget = $targets->getNode(1); + $valueTarget = new AssignNameExpression($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine()); + } else { + $keyTarget = new AssignNameExpression('_key', $lineno); + $valueTarget = $targets->getNode(0); + $valueTarget = new AssignNameExpression($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine()); + } + + if ($ifexpr) { + $this->checkLoopUsageCondition($stream, $ifexpr); + $this->checkLoopUsageBody($stream, $body); + } + + return new ForNode($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, $lineno, $this->getTag()); + } + + public function decideForFork(Token $token) + { + return $token->test(['else', 'endfor']); + } + + public function decideForEnd(Token $token) + { + return $token->test('endfor'); + } + + // the loop variable cannot be used in the condition + protected function checkLoopUsageCondition(TokenStream $stream, \Twig_NodeInterface $node) + { + if ($node instanceof GetAttrExpression && $node->getNode('node') instanceof NameExpression && 'loop' == $node->getNode('node')->getAttribute('name')) { + throw new SyntaxError('The "loop" variable cannot be used in a looping condition.', $node->getTemplateLine(), $stream->getSourceContext()); + } + + foreach ($node as $n) { + if (!$n) { + continue; + } + + $this->checkLoopUsageCondition($stream, $n); + } + } + + // check usage of non-defined loop-items + // it does not catch all problems (for instance when a for is included into another or when the variable is used in an include) + protected function checkLoopUsageBody(TokenStream $stream, \Twig_NodeInterface $node) + { + if ($node instanceof GetAttrExpression && $node->getNode('node') instanceof NameExpression && 'loop' == $node->getNode('node')->getAttribute('name')) { + $attribute = $node->getNode('attribute'); + if ($attribute instanceof ConstantExpression && \in_array($attribute->getAttribute('value'), ['length', 'revindex0', 'revindex', 'last'])) { + throw new SyntaxError(sprintf('The "loop.%s" variable is not defined when looping with a condition.', $attribute->getAttribute('value')), $node->getTemplateLine(), $stream->getSourceContext()); + } + } + + // should check for parent.loop.XXX usage + if ($node instanceof ForNode) { + return; + } + + foreach ($node as $n) { + if (!$n) { + continue; + } + + $this->checkLoopUsageBody($stream, $n); + } + } + + public function getTag() + { + return 'for'; + } +} + +class_alias('Twig\TokenParser\ForTokenParser', 'Twig_TokenParser_For'); diff --git a/system/libs/Twig/TokenParser/From.php b/system/libs/Twig/TokenParser/From.php deleted file mode 100755 index f3053da4..00000000 --- a/system/libs/Twig/TokenParser/From.php +++ /dev/null @@ -1,66 +0,0 @@ - - * {% from 'forms.html' import forms %} - * - * - * @final - */ -class Twig_TokenParser_From extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $macro = $this->parser->getExpressionParser()->parseExpression(); - $stream = $this->parser->getStream(); - $stream->expect('import'); - - $targets = array(); - do { - $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); - - $alias = $name; - if ($stream->nextIf('as')) { - $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); - } - - $targets[$name] = $alias; - - if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { - break; - } - } while (true); - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - $node = new Twig_Node_Import($macro, new Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()), $token->getLine(), $this->getTag()); - - foreach ($targets as $name => $alias) { - if ($this->parser->isReservedMacroName($name)) { - throw new Twig_Error_Syntax(sprintf('"%s" cannot be an imported macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext()); - } - - $this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var')); - } - - return $node; - } - - public function getTag() - { - return 'from'; - } -} - -class_alias('Twig_TokenParser_From', 'Twig\TokenParser\FromTokenParser', false); diff --git a/system/libs/Twig/TokenParser/FromTokenParser.php b/system/libs/Twig/TokenParser/FromTokenParser.php new file mode 100644 index 00000000..4cce650d --- /dev/null +++ b/system/libs/Twig/TokenParser/FromTokenParser.php @@ -0,0 +1,72 @@ +parser->getExpressionParser()->parseExpression(); + $stream = $this->parser->getStream(); + $stream->expect(Token::NAME_TYPE, 'import'); + + $targets = []; + do { + $name = $stream->expect(Token::NAME_TYPE)->getValue(); + + $alias = $name; + if ($stream->nextIf('as')) { + $alias = $stream->expect(Token::NAME_TYPE)->getValue(); + } + + $targets[$name] = $alias; + + if (!$stream->nextIf(Token::PUNCTUATION_TYPE, ',')) { + break; + } + } while (true); + + $stream->expect(Token::BLOCK_END_TYPE); + + $var = new AssignNameExpression($this->parser->getVarName(), $token->getLine()); + $node = new ImportNode($macro, $var, $token->getLine(), $this->getTag()); + + foreach ($targets as $name => $alias) { + if ($this->parser->isReservedMacroName($name)) { + throw new SyntaxError(sprintf('"%s" cannot be an imported macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext()); + } + + $this->parser->addImportedSymbol('function', $alias, 'get'.$name, $var); + } + + return $node; + } + + public function getTag() + { + return 'from'; + } +} + +class_alias('Twig\TokenParser\FromTokenParser', 'Twig_TokenParser_From'); diff --git a/system/libs/Twig/TokenParser/If.php b/system/libs/Twig/TokenParser/If.php deleted file mode 100755 index f081df3a..00000000 --- a/system/libs/Twig/TokenParser/If.php +++ /dev/null @@ -1,86 +0,0 @@ - - * {% if users %} - *
      - * {% for user in users %} - *
    • {{ user.username|e }}
    • - * {% endfor %} - *
    - * {% endif %} - * - * - * @final - */ -class Twig_TokenParser_If extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $expr = $this->parser->getExpressionParser()->parseExpression(); - $stream = $this->parser->getStream(); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideIfFork')); - $tests = array($expr, $body); - $else = null; - - $end = false; - while (!$end) { - switch ($stream->next()->getValue()) { - case 'else': - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $else = $this->parser->subparse(array($this, 'decideIfEnd')); - break; - - case 'elseif': - $expr = $this->parser->getExpressionParser()->parseExpression(); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideIfFork')); - $tests[] = $expr; - $tests[] = $body; - break; - - case 'endif': - $end = true; - break; - - default: - throw new Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d).', $lineno), $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - } - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - return new Twig_Node_If(new Twig_Node($tests), $else, $lineno, $this->getTag()); - } - - public function decideIfFork(Twig_Token $token) - { - return $token->test(array('elseif', 'else', 'endif')); - } - - public function decideIfEnd(Twig_Token $token) - { - return $token->test(array('endif')); - } - - public function getTag() - { - return 'if'; - } -} - -class_alias('Twig_TokenParser_If', 'Twig\TokenParser\IfTokenParser', false); diff --git a/system/libs/Twig/TokenParser/IfTokenParser.php b/system/libs/Twig/TokenParser/IfTokenParser.php new file mode 100644 index 00000000..2631a20c --- /dev/null +++ b/system/libs/Twig/TokenParser/IfTokenParser.php @@ -0,0 +1,91 @@ + + * {% for user in users %} + *
  • {{ user.username|e }}
  • + * {% endfor %} + * + * {% endif %} + * + * @final + */ +class IfTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $lineno = $token->getLine(); + $expr = $this->parser->getExpressionParser()->parseExpression(); + $stream = $this->parser->getStream(); + $stream->expect(Token::BLOCK_END_TYPE); + $body = $this->parser->subparse([$this, 'decideIfFork']); + $tests = [$expr, $body]; + $else = null; + + $end = false; + while (!$end) { + switch ($stream->next()->getValue()) { + case 'else': + $stream->expect(Token::BLOCK_END_TYPE); + $else = $this->parser->subparse([$this, 'decideIfEnd']); + break; + + case 'elseif': + $expr = $this->parser->getExpressionParser()->parseExpression(); + $stream->expect(Token::BLOCK_END_TYPE); + $body = $this->parser->subparse([$this, 'decideIfFork']); + $tests[] = $expr; + $tests[] = $body; + break; + + case 'endif': + $end = true; + break; + + default: + 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()); + } + } + + $stream->expect(Token::BLOCK_END_TYPE); + + return new IfNode(new Node($tests), $else, $lineno, $this->getTag()); + } + + public function decideIfFork(Token $token) + { + return $token->test(['elseif', 'else', 'endif']); + } + + public function decideIfEnd(Token $token) + { + return $token->test(['endif']); + } + + public function getTag() + { + return 'if'; + } +} + +class_alias('Twig\TokenParser\IfTokenParser', 'Twig_TokenParser_If'); diff --git a/system/libs/Twig/TokenParser/Import.php b/system/libs/Twig/TokenParser/Import.php deleted file mode 100755 index 47802f50..00000000 --- a/system/libs/Twig/TokenParser/Import.php +++ /dev/null @@ -1,41 +0,0 @@ - - * {% import 'forms.html' as forms %} - * - * - * @final - */ -class Twig_TokenParser_Import extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $macro = $this->parser->getExpressionParser()->parseExpression(); - $this->parser->getStream()->expect('as'); - $var = new Twig_Node_Expression_AssignName($this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(), $token->getLine()); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - - $this->parser->addImportedSymbol('template', $var->getAttribute('name')); - - return new Twig_Node_Import($macro, $var, $token->getLine(), $this->getTag()); - } - - public function getTag() - { - return 'import'; - } -} - -class_alias('Twig_TokenParser_Import', 'Twig\TokenParser\ImportTokenParser', false); diff --git a/system/libs/Twig/TokenParser/ImportTokenParser.php b/system/libs/Twig/TokenParser/ImportTokenParser.php new file mode 100644 index 00000000..88395b92 --- /dev/null +++ b/system/libs/Twig/TokenParser/ImportTokenParser.php @@ -0,0 +1,45 @@ +parser->getExpressionParser()->parseExpression(); + $this->parser->getStream()->expect(Token::NAME_TYPE, 'as'); + $var = new AssignNameExpression($this->parser->getStream()->expect(Token::NAME_TYPE)->getValue(), $token->getLine()); + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + + $this->parser->addImportedSymbol('template', $var->getAttribute('name')); + + return new ImportNode($macro, $var, $token->getLine(), $this->getTag()); + } + + public function getTag() + { + return 'import'; + } +} + +class_alias('Twig\TokenParser\ImportTokenParser', 'Twig_TokenParser_Import'); diff --git a/system/libs/Twig/TokenParser/Include.php b/system/libs/Twig/TokenParser/IncludeTokenParser.php old mode 100755 new mode 100644 similarity index 57% rename from system/libs/Twig/TokenParser/Include.php rename to system/libs/Twig/TokenParser/IncludeTokenParser.php index 309f11db..57aa4cf4 --- a/system/libs/Twig/TokenParser/Include.php +++ b/system/libs/Twig/TokenParser/IncludeTokenParser.php @@ -10,24 +10,27 @@ * file that was distributed with this source code. */ +namespace Twig\TokenParser; + +use Twig\Node\IncludeNode; +use Twig\Token; + /** * Includes a template. * - *
      *   {% include 'header.html' %}
      *     Body
      *   {% include 'footer.html' %}
    - * 
    */ -class Twig_TokenParser_Include extends Twig_TokenParser +class IncludeTokenParser extends AbstractTokenParser { - public function parse(Twig_Token $token) + public function parse(Token $token) { $expr = $this->parser->getExpressionParser()->parseExpression(); list($variables, $only, $ignoreMissing) = $this->parseArguments(); - return new Twig_Node_Include($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); + return new IncludeNode($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); } protected function parseArguments() @@ -35,25 +38,25 @@ class Twig_TokenParser_Include extends Twig_TokenParser $stream = $this->parser->getStream(); $ignoreMissing = false; - if ($stream->nextIf(Twig_Token::NAME_TYPE, 'ignore')) { - $stream->expect(Twig_Token::NAME_TYPE, 'missing'); + if ($stream->nextIf(Token::NAME_TYPE, 'ignore')) { + $stream->expect(Token::NAME_TYPE, 'missing'); $ignoreMissing = true; } $variables = null; - if ($stream->nextIf(Twig_Token::NAME_TYPE, 'with')) { + if ($stream->nextIf(Token::NAME_TYPE, 'with')) { $variables = $this->parser->getExpressionParser()->parseExpression(); } $only = false; - if ($stream->nextIf(Twig_Token::NAME_TYPE, 'only')) { + if ($stream->nextIf(Token::NAME_TYPE, 'only')) { $only = true; } - $stream->expect(Twig_Token::BLOCK_END_TYPE); + $stream->expect(Token::BLOCK_END_TYPE); - return array($variables, $only, $ignoreMissing); + return [$variables, $only, $ignoreMissing]; } public function getTag() @@ -62,4 +65,4 @@ class Twig_TokenParser_Include extends Twig_TokenParser } } -class_alias('Twig_TokenParser_Include', 'Twig\TokenParser\IncludeTokenParser', false); +class_alias('Twig\TokenParser\IncludeTokenParser', 'Twig_TokenParser_Include'); diff --git a/system/libs/Twig/TokenParser/Macro.php b/system/libs/Twig/TokenParser/Macro.php deleted file mode 100755 index 4287934b..00000000 --- a/system/libs/Twig/TokenParser/Macro.php +++ /dev/null @@ -1,60 +0,0 @@ - - * {% macro input(name, value, type, size) %} - * - * {% endmacro %} - * - * - * @final - */ -class Twig_TokenParser_Macro extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); - - $arguments = $this->parser->getExpressionParser()->parseArguments(true, true); - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $this->parser->pushLocalScope(); - $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - if ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) { - $value = $token->getValue(); - - if ($value != $name) { - throw new Twig_Error_Syntax(sprintf('Expected endmacro for macro "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - } - $this->parser->popLocalScope(); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - $this->parser->setMacro($name, new Twig_Node_Macro($name, new Twig_Node_Body(array($body)), $arguments, $lineno, $this->getTag())); - } - - public function decideBlockEnd(Twig_Token $token) - { - return $token->test('endmacro'); - } - - public function getTag() - { - return 'macro'; - } -} - -class_alias('Twig_TokenParser_Macro', 'Twig\TokenParser\MacroTokenParser', false); diff --git a/system/libs/Twig/TokenParser/MacroTokenParser.php b/system/libs/Twig/TokenParser/MacroTokenParser.php new file mode 100644 index 00000000..a0d66e7b --- /dev/null +++ b/system/libs/Twig/TokenParser/MacroTokenParser.php @@ -0,0 +1,68 @@ + + * {% endmacro %} + * + * @final + */ +class MacroTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + $name = $stream->expect(Token::NAME_TYPE)->getValue(); + + $arguments = $this->parser->getExpressionParser()->parseArguments(true, true); + + $stream->expect(Token::BLOCK_END_TYPE); + $this->parser->pushLocalScope(); + $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); + if ($token = $stream->nextIf(Token::NAME_TYPE)) { + $value = $token->getValue(); + + if ($value != $name) { + throw new SyntaxError(sprintf('Expected endmacro for macro "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + } + $this->parser->popLocalScope(); + $stream->expect(Token::BLOCK_END_TYPE); + + $this->parser->setMacro($name, new MacroNode($name, new BodyNode([$body]), $arguments, $lineno, $this->getTag())); + + return new Node(); + } + + public function decideBlockEnd(Token $token) + { + return $token->test('endmacro'); + } + + public function getTag() + { + return 'macro'; + } +} + +class_alias('Twig\TokenParser\MacroTokenParser', 'Twig_TokenParser_Macro'); diff --git a/system/libs/Twig/TokenParser/Sandbox.php b/system/libs/Twig/TokenParser/Sandbox.php deleted file mode 100755 index b8f581cb..00000000 --- a/system/libs/Twig/TokenParser/Sandbox.php +++ /dev/null @@ -1,61 +0,0 @@ - - * {% sandbox %} - * {% include 'user.html' %} - * {% endsandbox %} - * - * - * @see http://www.twig-project.org/doc/api.html#sandbox-extension for details - * - * @final - */ -class Twig_TokenParser_Sandbox extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $stream = $this->parser->getStream(); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - // in a sandbox tag, only include tags are allowed - if (!$body instanceof Twig_Node_Include) { - foreach ($body as $node) { - if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) { - continue; - } - - if (!$node instanceof Twig_Node_Include) { - throw new Twig_Error_Syntax('Only "include" tags are allowed within a "sandbox" section.', $node->getTemplateLine(), $stream->getSourceContext()); - } - } - } - - return new Twig_Node_Sandbox($body, $token->getLine(), $this->getTag()); - } - - public function decideBlockEnd(Twig_Token $token) - { - return $token->test('endsandbox'); - } - - public function getTag() - { - return 'sandbox'; - } -} - -class_alias('Twig_TokenParser_Sandbox', 'Twig\TokenParser\SandboxTokenParser', false); diff --git a/system/libs/Twig/TokenParser/SandboxTokenParser.php b/system/libs/Twig/TokenParser/SandboxTokenParser.php new file mode 100644 index 00000000..0f3ad9e3 --- /dev/null +++ b/system/libs/Twig/TokenParser/SandboxTokenParser.php @@ -0,0 +1,67 @@ +parser->getStream(); + $stream->expect(Token::BLOCK_END_TYPE); + $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); + $stream->expect(Token::BLOCK_END_TYPE); + + // in a sandbox tag, only include tags are allowed + if (!$body instanceof IncludeNode) { + foreach ($body as $node) { + if ($node instanceof TextNode && ctype_space($node->getAttribute('data'))) { + continue; + } + + if (!$node instanceof IncludeNode) { + throw new SyntaxError('Only "include" tags are allowed within a "sandbox" section.', $node->getTemplateLine(), $stream->getSourceContext()); + } + } + } + + return new SandboxNode($body, $token->getLine(), $this->getTag()); + } + + public function decideBlockEnd(Token $token) + { + return $token->test('endsandbox'); + } + + public function getTag() + { + return 'sandbox'; + } +} + +class_alias('Twig\TokenParser\SandboxTokenParser', 'Twig_TokenParser_Sandbox'); diff --git a/system/libs/Twig/TokenParser/Set.php b/system/libs/Twig/TokenParser/Set.php deleted file mode 100755 index 48c6b3ae..00000000 --- a/system/libs/Twig/TokenParser/Set.php +++ /dev/null @@ -1,75 +0,0 @@ - - * {% set foo = 'foo' %} - * - * {% set foo = [1, 2] %} - * - * {% set foo = {'foo': 'bar'} %} - * - * {% set foo = 'foo' ~ 'bar' %} - * - * {% set foo, bar = 'foo', 'bar' %} - * - * {% set foo %}Some content{% endset %} - * - * - * @final - */ -class Twig_TokenParser_Set extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - $names = $this->parser->getExpressionParser()->parseAssignmentExpression(); - - $capture = false; - if ($stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) { - $values = $this->parser->getExpressionParser()->parseMultitargetExpression(); - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - if (count($names) !== count($values)) { - throw new Twig_Error_Syntax('When using set, you must have the same number of variables and assignments.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - } else { - $capture = true; - - if (count($names) > 1) { - throw new Twig_Error_Syntax('When using set with a block, you cannot have a multi-target.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - $values = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - } - - return new Twig_Node_Set($capture, $names, $values, $lineno, $this->getTag()); - } - - public function decideBlockEnd(Twig_Token $token) - { - return $token->test('endset'); - } - - public function getTag() - { - return 'set'; - } -} - -class_alias('Twig_TokenParser_Set', 'Twig\TokenParser\SetTokenParser', false); diff --git a/system/libs/Twig/TokenParser/SetTokenParser.php b/system/libs/Twig/TokenParser/SetTokenParser.php new file mode 100644 index 00000000..eebebc69 --- /dev/null +++ b/system/libs/Twig/TokenParser/SetTokenParser.php @@ -0,0 +1,74 @@ +getLine(); + $stream = $this->parser->getStream(); + $names = $this->parser->getExpressionParser()->parseAssignmentExpression(); + + $capture = false; + if ($stream->nextIf(Token::OPERATOR_TYPE, '=')) { + $values = $this->parser->getExpressionParser()->parseMultitargetExpression(); + + $stream->expect(Token::BLOCK_END_TYPE); + + if (\count($names) !== \count($values)) { + throw new SyntaxError('When using set, you must have the same number of variables and assignments.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + } else { + $capture = true; + + if (\count($names) > 1) { + throw new SyntaxError('When using set with a block, you cannot have a multi-target.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + + $stream->expect(Token::BLOCK_END_TYPE); + + $values = $this->parser->subparse([$this, 'decideBlockEnd'], true); + $stream->expect(Token::BLOCK_END_TYPE); + } + + return new SetNode($capture, $names, $values, $lineno, $this->getTag()); + } + + public function decideBlockEnd(Token $token) + { + return $token->test('endset'); + } + + public function getTag() + { + return 'set'; + } +} + +class_alias('Twig\TokenParser\SetTokenParser', 'Twig_TokenParser_Set'); diff --git a/system/libs/Twig/TokenParser/Spaceless.php b/system/libs/Twig/TokenParser/Spaceless.php deleted file mode 100755 index cecf27c6..00000000 --- a/system/libs/Twig/TokenParser/Spaceless.php +++ /dev/null @@ -1,51 +0,0 @@ - - * {% spaceless %} - *
    - * foo - *
    - * {% endspaceless %} - * - * {# output will be
    foo
    #} - * - * - * @final - */ -class Twig_TokenParser_Spaceless extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideSpacelessEnd'), true); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - - return new Twig_Node_Spaceless($body, $lineno, $this->getTag()); - } - - public function decideSpacelessEnd(Twig_Token $token) - { - return $token->test('endspaceless'); - } - - public function getTag() - { - return 'spaceless'; - } -} - -class_alias('Twig_TokenParser_Spaceless', 'Twig\TokenParser\SpacelessTokenParser', false); diff --git a/system/libs/Twig/TokenParser/SpacelessTokenParser.php b/system/libs/Twig/TokenParser/SpacelessTokenParser.php new file mode 100644 index 00000000..5b5656bc --- /dev/null +++ b/system/libs/Twig/TokenParser/SpacelessTokenParser.php @@ -0,0 +1,53 @@ + + * foo + * + * {% endspaceless %} + * {# output will be
    foo
    #} + * + * @final + */ +class SpacelessTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $lineno = $token->getLine(); + + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + $body = $this->parser->subparse([$this, 'decideSpacelessEnd'], true); + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + + return new SpacelessNode($body, $lineno, $this->getTag()); + } + + public function decideSpacelessEnd(Token $token) + { + return $token->test('endspaceless'); + } + + public function getTag() + { + return 'spaceless'; + } +} + +class_alias('Twig\TokenParser\SpacelessTokenParser', 'Twig_TokenParser_Spaceless'); diff --git a/system/libs/Twig/TokenParserInterface.php b/system/libs/Twig/TokenParser/TokenParserInterface.php old mode 100755 new mode 100644 similarity index 53% rename from system/libs/Twig/TokenParserInterface.php rename to system/libs/Twig/TokenParser/TokenParserInterface.php index 14acc808..4b603b21 --- a/system/libs/Twig/TokenParserInterface.php +++ b/system/libs/Twig/TokenParser/TokenParserInterface.php @@ -9,26 +9,32 @@ * file that was distributed with this source code. */ +namespace Twig\TokenParser; + +use Twig\Error\SyntaxError; +use Twig\Parser; +use Twig\Token; + /** * Interface implemented by token parsers. * * @author Fabien Potencier */ -interface Twig_TokenParserInterface +interface TokenParserInterface { /** * Sets the parser associated with this token parser. */ - public function setParser(Twig_Parser $parser); + public function setParser(Parser $parser); /** * Parses a token and returns a node. * - * @return Twig_NodeInterface + * @return \Twig_NodeInterface * - * @throws Twig_Error_Syntax + * @throws SyntaxError */ - public function parse(Twig_Token $token); + public function parse(Token $token); /** * Gets the tag name associated with this token parser. @@ -38,6 +44,8 @@ interface Twig_TokenParserInterface public function getTag(); } -class_alias('Twig_TokenParserInterface', 'Twig\TokenParser\TokenParserInterface', false); -class_exists('Twig_Parser'); -class_exists('Twig_Token'); +class_alias('Twig\TokenParser\TokenParserInterface', 'Twig_TokenParserInterface'); + +// Ensure that the aliased name is loaded to keep BC for classes implementing the typehint with the old aliased name. +class_exists('Twig\Token'); +class_exists('Twig\Parser'); diff --git a/system/libs/Twig/TokenParser/Use.php b/system/libs/Twig/TokenParser/Use.php deleted file mode 100755 index f15a91ea..00000000 --- a/system/libs/Twig/TokenParser/Use.php +++ /dev/null @@ -1,70 +0,0 @@ - - * {% extends "base.html" %} - * - * {% use "blocks.html" %} - * - * {% block title %}{% endblock %} - * {% block content %}{% endblock %} - * - * - * @see http://www.twig-project.org/doc/templates.html#horizontal-reuse for details. - * - * @final - */ -class Twig_TokenParser_Use extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $template = $this->parser->getExpressionParser()->parseExpression(); - $stream = $this->parser->getStream(); - - if (!$template instanceof Twig_Node_Expression_Constant) { - throw new Twig_Error_Syntax('The template references in a "use" statement must be a string.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - - $targets = array(); - if ($stream->nextIf('with')) { - do { - $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); - - $alias = $name; - if ($stream->nextIf('as')) { - $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); - } - - $targets[$name] = new Twig_Node_Expression_Constant($alias, -1); - - if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { - break; - } - } while (true); - } - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - $this->parser->addTrait(new Twig_Node(array('template' => $template, 'targets' => new Twig_Node($targets)))); - - return new Twig_Node(); - } - - public function getTag() - { - return 'use'; - } -} - -class_alias('Twig_TokenParser_Use', 'Twig\TokenParser\UseTokenParser', false); diff --git a/system/libs/Twig/TokenParser/UseTokenParser.php b/system/libs/Twig/TokenParser/UseTokenParser.php new file mode 100644 index 00000000..d2e39aab --- /dev/null +++ b/system/libs/Twig/TokenParser/UseTokenParser.php @@ -0,0 +1,75 @@ +parser->getExpressionParser()->parseExpression(); + $stream = $this->parser->getStream(); + + if (!$template instanceof ConstantExpression) { + throw new SyntaxError('The template references in a "use" statement must be a string.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + + $targets = []; + if ($stream->nextIf('with')) { + do { + $name = $stream->expect(Token::NAME_TYPE)->getValue(); + + $alias = $name; + if ($stream->nextIf('as')) { + $alias = $stream->expect(Token::NAME_TYPE)->getValue(); + } + + $targets[$name] = new ConstantExpression($alias, -1); + + if (!$stream->nextIf(Token::PUNCTUATION_TYPE, ',')) { + break; + } + } while (true); + } + + $stream->expect(Token::BLOCK_END_TYPE); + + $this->parser->addTrait(new Node(['template' => $template, 'targets' => new Node($targets)])); + + return new Node(); + } + + public function getTag() + { + return 'use'; + } +} + +class_alias('Twig\TokenParser\UseTokenParser', 'Twig_TokenParser_Use'); diff --git a/system/libs/Twig/TokenParser/With.php b/system/libs/Twig/TokenParser/With.php deleted file mode 100644 index 7a692597..00000000 --- a/system/libs/Twig/TokenParser/With.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * @final - */ -class Twig_TokenParser_With extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $stream = $this->parser->getStream(); - - $variables = null; - $only = false; - if (!$stream->test(Twig_Token::BLOCK_END_TYPE)) { - $variables = $this->parser->getExpressionParser()->parseExpression(); - $only = $stream->nextIf(Twig_Token::NAME_TYPE, 'only'); - } - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - $body = $this->parser->subparse(array($this, 'decideWithEnd'), true); - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - return new Twig_Node_With($body, $variables, $only, $token->getLine(), $this->getTag()); - } - - public function decideWithEnd(Twig_Token $token) - { - return $token->test('endwith'); - } - - public function getTag() - { - return 'with'; - } -} - -class_alias('Twig_TokenParser_With', 'Twig\TokenParser\WithTokenParser', false); diff --git a/system/libs/Twig/TokenParser/WithTokenParser.php b/system/libs/Twig/TokenParser/WithTokenParser.php new file mode 100644 index 00000000..411e2b4a --- /dev/null +++ b/system/libs/Twig/TokenParser/WithTokenParser.php @@ -0,0 +1,57 @@ + + * + * @final + */ +class WithTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $stream = $this->parser->getStream(); + + $variables = null; + $only = false; + if (!$stream->test(Token::BLOCK_END_TYPE)) { + $variables = $this->parser->getExpressionParser()->parseExpression(); + $only = $stream->nextIf(Token::NAME_TYPE, 'only'); + } + + $stream->expect(Token::BLOCK_END_TYPE); + + $body = $this->parser->subparse([$this, 'decideWithEnd'], true); + + $stream->expect(Token::BLOCK_END_TYPE); + + return new WithNode($body, $variables, $only, $token->getLine(), $this->getTag()); + } + + public function decideWithEnd(Token $token) + { + return $token->test('endwith'); + } + + public function getTag() + { + return 'with'; + } +} + +class_alias('Twig\TokenParser\WithTokenParser', 'Twig_TokenParser_With'); diff --git a/system/libs/Twig/TokenStream.php b/system/libs/Twig/TokenStream.php index e1bd7ca1..45978169 100755 --- a/system/libs/Twig/TokenStream.php +++ b/system/libs/Twig/TokenStream.php @@ -10,6 +10,10 @@ * file that was distributed with this source code. */ +namespace Twig; + +use Twig\Error\SyntaxError; + /** * Represents a token stream. * @@ -17,7 +21,7 @@ * * @author Fabien Potencier */ -class Twig_TokenStream +class TokenStream { protected $tokens; protected $current = 0; @@ -32,11 +36,11 @@ class Twig_TokenStream */ public function __construct(array $tokens, $name = null, $source = null) { - if (!$name instanceof Twig_Source) { + if (!$name instanceof Source) { if (null !== $name || null !== $source) { - @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); + @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); } - $this->source = new Twig_Source($source, $name); + $this->source = new Source($source, $name); } else { $this->source = $name; } @@ -54,18 +58,18 @@ class Twig_TokenStream public function injectTokens(array $tokens) { - $this->tokens = array_merge(array_slice($this->tokens, 0, $this->current), $tokens, array_slice($this->tokens, $this->current)); + $this->tokens = array_merge(\array_slice($this->tokens, 0, $this->current), $tokens, \array_slice($this->tokens, $this->current)); } /** * Sets the pointer to the next token and returns the old one. * - * @return Twig_Token + * @return Token */ public function next() { if (!isset($this->tokens[++$this->current])) { - throw new Twig_Error_Syntax('Unexpected end of template.', $this->tokens[$this->current - 1]->getLine(), $this->source); + throw new SyntaxError('Unexpected end of template.', $this->tokens[$this->current - 1]->getLine(), $this->source); } return $this->tokens[$this->current - 1]; @@ -74,7 +78,7 @@ class Twig_TokenStream /** * Tests a token, sets the pointer to the next one and returns it or throws a syntax error. * - * @return Twig_Token|null The next token if the condition is true, null otherwise + * @return Token|null The next token if the condition is true, null otherwise */ public function nextIf($primary, $secondary = null) { @@ -86,17 +90,18 @@ class Twig_TokenStream /** * Tests a token and returns it or throws a syntax error. * - * @return Twig_Token + * @return Token */ public function expect($type, $value = null, $message = null) { $token = $this->tokens[$this->current]; if (!$token->test($type, $value)) { $line = $token->getLine(); - throw new Twig_Error_Syntax(sprintf('%sUnexpected token "%s" of value "%s" ("%s" expected%s).', + throw new SyntaxError(sprintf('%sUnexpected token "%s"%s ("%s" expected%s).', $message ? $message.'. ' : '', - Twig_Token::typeToEnglish($token->getType()), $token->getValue(), - Twig_Token::typeToEnglish($type), $value ? sprintf(' with value "%s"', $value) : ''), + Token::typeToEnglish($token->getType()), + $token->getValue() ? sprintf(' of value "%s"', $token->getValue()) : '', + Token::typeToEnglish($type), $value ? sprintf(' with value "%s"', $value) : ''), $line, $this->source ); @@ -111,12 +116,12 @@ class Twig_TokenStream * * @param int $number * - * @return Twig_Token + * @return Token */ public function look($number = 1) { if (!isset($this->tokens[$this->current + $number])) { - throw new Twig_Error_Syntax('Unexpected end of template.', $this->tokens[$this->current + $number - 1]->getLine(), $this->source); + throw new SyntaxError('Unexpected end of template.', $this->tokens[$this->current + $number - 1]->getLine(), $this->source); } return $this->tokens[$this->current + $number]; @@ -139,11 +144,11 @@ class Twig_TokenStream */ public function isEOF() { - return $this->tokens[$this->current]->getType() === Twig_Token::EOF_TYPE; + return Token::EOF_TYPE === $this->tokens[$this->current]->getType(); } /** - * @return Twig_Token + * @return Token */ public function getCurrent() { @@ -183,7 +188,7 @@ class Twig_TokenStream /** * Gets the source associated with this stream. * - * @return Twig_Source + * @return Source * * @internal */ @@ -193,4 +198,4 @@ class Twig_TokenStream } } -class_alias('Twig_TokenStream', 'Twig\TokenStream', false); +class_alias('Twig\TokenStream', 'Twig_TokenStream'); diff --git a/system/libs/Twig/Twig/Autoloader.php b/system/libs/Twig/Twig/Autoloader.php new file mode 100644 index 00000000..e34e2144 --- /dev/null +++ b/system/libs/Twig/Twig/Autoloader.php @@ -0,0 +1,52 @@ + + * + * @deprecated since 1.21 and will be removed in 2.0. Use Composer instead. 2.0. + */ +class Twig_Autoloader +{ + /** + * Registers Twig_Autoloader as an SPL autoloader. + * + * @param bool $prepend whether to prepend the autoloader or not + */ + public static function register($prepend = false) + { + @trigger_error('Using Twig_Autoloader is deprecated since version 1.21. Use Composer instead.', E_USER_DEPRECATED); + + spl_autoload_register([__CLASS__, 'autoload'], true, $prepend); + } + + /** + * Handles autoloading of classes. + * + * @param string $class a class name + */ + public static function autoload($class) + { + if (0 !== strpos($class, 'Twig')) { + return; + } + + if (is_file($file = __DIR__.'/../'.str_replace(['_', "\0"], ['/', ''], $class).'.php')) { + require $file; + } elseif (is_file($file = __DIR__.'/../../src/'.str_replace(['Twig\\', '\\', "\0"], ['', '/', ''], $class).'.php')) { + require $file; + } + } +} diff --git a/system/libs/Twig/Twig/BaseNodeVisitor.php b/system/libs/Twig/Twig/BaseNodeVisitor.php new file mode 100644 index 00000000..fe99b258 --- /dev/null +++ b/system/libs/Twig/Twig/BaseNodeVisitor.php @@ -0,0 +1,11 @@ + * @@ -23,17 +25,17 @@ abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableInterface { protected $options; - protected $arguments = array(); + protected $arguments = []; - public function __construct(array $options = array()) + public function __construct(array $options = []) { - $this->options = array_merge(array( + $this->options = array_merge([ 'needs_environment' => false, 'needs_context' => false, 'pre_escape' => null, 'preserves_safety' => null, 'callable' => null, - ), $options); + ], $options); } public function setArguments($arguments) @@ -56,14 +58,14 @@ abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableI return $this->options['needs_context']; } - public function getSafe(Twig_Node $filterArgs) + public function getSafe(Node $filterArgs) { if (isset($this->options['is_safe'])) { return $this->options['is_safe']; } if (isset($this->options['is_safe_callback'])) { - return call_user_func($this->options['is_safe_callback'], $filterArgs); + return \call_user_func($this->options['is_safe_callback'], $filterArgs); } } diff --git a/system/libs/Twig/Filter/Function.php b/system/libs/Twig/Twig/Filter/Function.php old mode 100755 new mode 100644 similarity index 77% rename from system/libs/Twig/Filter/Function.php rename to system/libs/Twig/Twig/Filter/Function.php index 71b16554..011d4ccf --- a/system/libs/Twig/Filter/Function.php +++ b/system/libs/Twig/Twig/Filter/Function.php @@ -9,12 +9,12 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Filter_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED); +@trigger_error('The Twig_Filter_Function class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFilter instead.', E_USER_DEPRECATED); /** * Represents a function template filter. * - * Use Twig_SimpleFilter instead. + * Use \Twig\TwigFilter instead. * * @author Fabien Potencier * @@ -24,7 +24,7 @@ class Twig_Filter_Function extends Twig_Filter { protected $function; - public function __construct($function, array $options = array()) + public function __construct($function, array $options = []) { $options['callable'] = $function; diff --git a/system/libs/Twig/Filter/Method.php b/system/libs/Twig/Twig/Filter/Method.php old mode 100755 new mode 100644 similarity index 61% rename from system/libs/Twig/Filter/Method.php rename to system/libs/Twig/Twig/Filter/Method.php index 1b75676c..5cd06282 --- a/system/libs/Twig/Filter/Method.php +++ b/system/libs/Twig/Twig/Filter/Method.php @@ -9,12 +9,14 @@ * file that was distributed with this source code. */ -@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); +use Twig\Extension\ExtensionInterface; + +@trigger_error('The Twig_Filter_Method class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFilter instead.', E_USER_DEPRECATED); /** * Represents a method template filter. * - * Use Twig_SimpleFilter instead. + * Use \Twig\TwigFilter instead. * * @author Fabien Potencier * @@ -25,9 +27,9 @@ class Twig_Filter_Method extends Twig_Filter protected $extension; protected $method; - public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array()) + public function __construct(ExtensionInterface $extension, $method, array $options = []) { - $options['callable'] = array($extension, $method); + $options['callable'] = [$extension, $method]; parent::__construct($options); @@ -37,6 +39,6 @@ class Twig_Filter_Method extends Twig_Filter public function compile() { - return sprintf('$this->env->getExtension(\'%s\')->%s', get_class($this->extension), $this->method); + return sprintf('$this->env->getExtension(\'%s\')->%s', \get_class($this->extension), $this->method); } } diff --git a/system/libs/Twig/Filter/Node.php b/system/libs/Twig/Twig/Filter/Node.php old mode 100755 new mode 100644 similarity index 78% rename from system/libs/Twig/Filter/Node.php rename to system/libs/Twig/Twig/Filter/Node.php index 3e6b12ef..8bb2899c --- a/system/libs/Twig/Filter/Node.php +++ b/system/libs/Twig/Twig/Filter/Node.php @@ -9,12 +9,12 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Filter_Node class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED); +@trigger_error('The Twig_Filter_Node class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFilter instead.', E_USER_DEPRECATED); /** * Represents a template filter as a node. * - * Use Twig_SimpleFilter instead. + * Use \Twig\TwigFilter instead. * * @author Fabien Potencier * @@ -24,7 +24,7 @@ class Twig_Filter_Node extends Twig_Filter { protected $class; - public function __construct($class, array $options = array()) + public function __construct($class, array $options = []) { parent::__construct($options); diff --git a/system/libs/Twig/FilterCallableInterface.php b/system/libs/Twig/Twig/FilterCallableInterface.php old mode 100755 new mode 100644 similarity index 92% rename from system/libs/Twig/FilterCallableInterface.php rename to system/libs/Twig/Twig/FilterCallableInterface.php index 21b028c4..091ca974 --- a/system/libs/Twig/FilterCallableInterface.php +++ b/system/libs/Twig/Twig/FilterCallableInterface.php @@ -12,7 +12,7 @@ /** * Represents a callable template filter. * - * Use Twig_SimpleFilter instead. + * Use \Twig\TwigFilter instead. * * @author Fabien Potencier * diff --git a/system/libs/Twig/FilterInterface.php b/system/libs/Twig/Twig/FilterInterface.php old mode 100755 new mode 100644 similarity index 88% rename from system/libs/Twig/FilterInterface.php rename to system/libs/Twig/Twig/FilterInterface.php index 9d7e9ab6..9b85f976 --- a/system/libs/Twig/FilterInterface.php +++ b/system/libs/Twig/Twig/FilterInterface.php @@ -9,10 +9,12 @@ * file that was distributed with this source code. */ +use Twig\Node\Node; + /** * Represents a template filter. * - * Use Twig_SimpleFilter instead. + * Use \Twig\TwigFilter instead. * * @author Fabien Potencier * @@ -31,7 +33,7 @@ interface Twig_FilterInterface public function needsContext(); - public function getSafe(Twig_Node $filterArgs); + public function getSafe(Node $filterArgs); public function getPreservesSafety(); diff --git a/system/libs/Twig/Function.php b/system/libs/Twig/Twig/Function.php old mode 100755 new mode 100644 similarity index 74% rename from system/libs/Twig/Function.php rename to system/libs/Twig/Twig/Function.php index 9dc16e90..6646e746 --- a/system/libs/Twig/Function.php +++ b/system/libs/Twig/Twig/Function.php @@ -9,12 +9,14 @@ * file that was distributed with this source code. */ -@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); +use Twig\Node\Node; + +@trigger_error('The Twig_Function class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFunction instead.', E_USER_DEPRECATED); /** * Represents a template function. * - * Use Twig_SimpleFunction instead. + * Use \Twig\TwigFunction instead. * * @author Fabien Potencier * @@ -23,15 +25,15 @@ abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCallableInterface { protected $options; - protected $arguments = array(); + protected $arguments = []; - public function __construct(array $options = array()) + public function __construct(array $options = []) { - $this->options = array_merge(array( + $this->options = array_merge([ 'needs_environment' => false, 'needs_context' => false, 'callable' => null, - ), $options); + ], $options); } public function setArguments($arguments) @@ -54,17 +56,17 @@ abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCal return $this->options['needs_context']; } - public function getSafe(Twig_Node $functionArgs) + public function getSafe(Node $functionArgs) { if (isset($this->options['is_safe'])) { return $this->options['is_safe']; } if (isset($this->options['is_safe_callback'])) { - return call_user_func($this->options['is_safe_callback'], $functionArgs); + return \call_user_func($this->options['is_safe_callback'], $functionArgs); } - return array(); + return []; } public function getCallable() diff --git a/system/libs/Twig/Function/Function.php b/system/libs/Twig/Twig/Function/Function.php old mode 100755 new mode 100644 similarity index 78% rename from system/libs/Twig/Function/Function.php rename to system/libs/Twig/Twig/Function/Function.php index 97c0eb77..605d8d33 --- a/system/libs/Twig/Function/Function.php +++ b/system/libs/Twig/Twig/Function/Function.php @@ -10,12 +10,12 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Function_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED); +@trigger_error('The Twig_Function_Function class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFunction instead.', E_USER_DEPRECATED); /** * Represents a function template function. * - * Use Twig_SimpleFunction instead. + * Use \Twig\TwigFunction instead. * * @author Arnaud Le Blanc * @@ -25,7 +25,7 @@ class Twig_Function_Function extends Twig_Function { protected $function; - public function __construct($function, array $options = array()) + public function __construct($function, array $options = []) { $options['callable'] = $function; diff --git a/system/libs/Twig/Function/Method.php b/system/libs/Twig/Twig/Function/Method.php old mode 100755 new mode 100644 similarity index 62% rename from system/libs/Twig/Function/Method.php rename to system/libs/Twig/Twig/Function/Method.php index 4299e118..9e472c5d --- a/system/libs/Twig/Function/Method.php +++ b/system/libs/Twig/Twig/Function/Method.php @@ -10,12 +10,14 @@ * file that was distributed with this source code. */ -@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); +use Twig\Extension\ExtensionInterface; + +@trigger_error('The Twig_Function_Method class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFunction instead.', E_USER_DEPRECATED); /** * Represents a method template function. * - * Use Twig_SimpleFunction instead. + * Use \Twig\TwigFunction instead. * * @author Arnaud Le Blanc * @@ -26,9 +28,9 @@ class Twig_Function_Method extends Twig_Function protected $extension; protected $method; - public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array()) + public function __construct(ExtensionInterface $extension, $method, array $options = []) { - $options['callable'] = array($extension, $method); + $options['callable'] = [$extension, $method]; parent::__construct($options); @@ -38,6 +40,6 @@ class Twig_Function_Method extends Twig_Function public function compile() { - return sprintf('$this->env->getExtension(\'%s\')->%s', get_class($this->extension), $this->method); + return sprintf('$this->env->getExtension(\'%s\')->%s', \get_class($this->extension), $this->method); } } diff --git a/system/libs/Twig/Function/Node.php b/system/libs/Twig/Twig/Function/Node.php old mode 100755 new mode 100644 similarity index 77% rename from system/libs/Twig/Function/Node.php rename to system/libs/Twig/Twig/Function/Node.php index 0adc5d93..8148ec32 --- a/system/libs/Twig/Function/Node.php +++ b/system/libs/Twig/Twig/Function/Node.php @@ -9,12 +9,12 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Function_Node class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED); +@trigger_error('The Twig_Function_Node class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFunction instead.', E_USER_DEPRECATED); /** * Represents a template function as a node. * - * Use Twig_SimpleFunction instead. + * Use \Twig\TwigFunction instead. * * @author Fabien Potencier * @@ -24,7 +24,7 @@ class Twig_Function_Node extends Twig_Function { protected $class; - public function __construct($class, array $options = array()) + public function __construct($class, array $options = []) { parent::__construct($options); diff --git a/system/libs/Twig/FunctionCallableInterface.php b/system/libs/Twig/Twig/FunctionCallableInterface.php old mode 100755 new mode 100644 similarity index 92% rename from system/libs/Twig/FunctionCallableInterface.php rename to system/libs/Twig/Twig/FunctionCallableInterface.php index d23d6917..abc83ea4 --- a/system/libs/Twig/FunctionCallableInterface.php +++ b/system/libs/Twig/Twig/FunctionCallableInterface.php @@ -12,7 +12,7 @@ /** * Represents a callable template function. * - * Use Twig_SimpleFunction instead. + * Use \Twig\TwigFunction instead. * * @author Fabien Potencier * diff --git a/system/libs/Twig/FunctionInterface.php b/system/libs/Twig/Twig/FunctionInterface.php old mode 100755 new mode 100644 similarity index 87% rename from system/libs/Twig/FunctionInterface.php rename to system/libs/Twig/Twig/FunctionInterface.php index 00d4f95c..915d6cc3 --- a/system/libs/Twig/FunctionInterface.php +++ b/system/libs/Twig/Twig/FunctionInterface.php @@ -10,10 +10,12 @@ * file that was distributed with this source code. */ +use Twig\Node\Node; + /** * Represents a template function. * - * Use Twig_SimpleFunction instead. + * Use \Twig\TwigFunction instead. * * @author Arnaud Le Blanc * @@ -32,7 +34,7 @@ interface Twig_FunctionInterface public function needsContext(); - public function getSafe(Twig_Node $filterArgs); + public function getSafe(Node $filterArgs); public function setArguments($arguments); diff --git a/system/libs/Twig/Twig/Lexer.php b/system/libs/Twig/Twig/Lexer.php new file mode 100644 index 00000000..00d74cc4 --- /dev/null +++ b/system/libs/Twig/Twig/Lexer.php @@ -0,0 +1,11 @@ + */ -class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface +class Twig_Loader_String implements LoaderInterface, ExistsLoaderInterface, SourceContextLoaderInterface { public function getSource($name) { - @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED); + @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', \get_class($this)), E_USER_DEPRECATED); return $name; } public function getSourceContext($name) { - return new Twig_Source($name, $name); + return new Source($name, $name); } public function exists($name) diff --git a/system/libs/Twig/Twig/LoaderInterface.php b/system/libs/Twig/Twig/LoaderInterface.php new file mode 100644 index 00000000..db515bbd --- /dev/null +++ b/system/libs/Twig/Twig/LoaderInterface.php @@ -0,0 +1,11 @@ + $name), $lineno, $tag); + parent::__construct([], ['name' => $name], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler->raw(sprintf("\$this->env->getExtension('%s')", $this->getAttribute('name'))); } diff --git a/system/libs/Twig/Twig/Node/Expression/Filter.php b/system/libs/Twig/Twig/Node/Expression/Filter.php new file mode 100644 index 00000000..85705715 --- /dev/null +++ b/system/libs/Twig/Twig/Node/Expression/Filter.php @@ -0,0 +1,11 @@ +options = array_merge(array( + $this->options = array_merge([ 'callable' => null, - ), $options); + ], $options); } public function getCallable() diff --git a/system/libs/Twig/Test/Function.php b/system/libs/Twig/Twig/Test/Function.php old mode 100755 new mode 100644 similarity index 81% rename from system/libs/Twig/Test/Function.php rename to system/libs/Twig/Twig/Test/Function.php index 9e83c3f8..a789c402 --- a/system/libs/Twig/Test/Function.php +++ b/system/libs/Twig/Twig/Test/Function.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Test_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleTest instead.', E_USER_DEPRECATED); +@trigger_error('The Twig_Test_Function class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigTest instead.', E_USER_DEPRECATED); /** * Represents a function template test. @@ -22,7 +22,7 @@ class Twig_Test_Function extends Twig_Test { protected $function; - public function __construct($function, array $options = array()) + public function __construct($function, array $options = []) { $options['callable'] = $function; diff --git a/system/libs/Twig/Twig/Test/IntegrationTestCase.php b/system/libs/Twig/Twig/Test/IntegrationTestCase.php new file mode 100644 index 00000000..e302bdba --- /dev/null +++ b/system/libs/Twig/Twig/Test/IntegrationTestCase.php @@ -0,0 +1,11 @@ +env->getExtension(\'%s\')->%s', get_class($this->extension), $this->method); + return sprintf('$this->env->getExtension(\'%s\')->%s', \get_class($this->extension), $this->method); } } diff --git a/system/libs/Twig/Test/Node.php b/system/libs/Twig/Twig/Test/Node.php old mode 100755 new mode 100644 similarity index 91% rename from system/libs/Twig/Test/Node.php rename to system/libs/Twig/Twig/Test/Node.php index 6098a527..6b5de159 --- a/system/libs/Twig/Test/Node.php +++ b/system/libs/Twig/Twig/Test/Node.php @@ -22,7 +22,7 @@ class Twig_Test_Node extends Twig_Test { protected $class; - public function __construct($class, array $options = array()) + public function __construct($class, array $options = []) { parent::__construct($options); diff --git a/system/libs/Twig/Twig/Test/NodeTestCase.php b/system/libs/Twig/Twig/Test/NodeTestCase.php new file mode 100644 index 00000000..62aaaaff --- /dev/null +++ b/system/libs/Twig/Twig/Test/NodeTestCase.php @@ -0,0 +1,11 @@ +parsers[$parser->getTag()] = $parser; } foreach ($brokers as $broker) { if (!$broker instanceof Twig_TokenParserBrokerInterface) { - throw new LogicException('$brokers must a an array of Twig_TokenParserBrokerInterface.'); + throw new \LogicException('$brokers must a an array of Twig_TokenParserBrokerInterface.'); } $this->brokers[] = $broker; } } - public function addTokenParser(Twig_TokenParserInterface $parser) + public function addTokenParser(TokenParserInterface $parser) { $this->parsers[$parser->getTag()] = $parser; } - public function removeTokenParser(Twig_TokenParserInterface $parser) + public function removeTokenParser(TokenParserInterface $parser) { $name = $parser->getTag(); if (isset($this->parsers[$name]) && $parser === $this->parsers[$name]) { @@ -61,12 +63,12 @@ class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface } } - public function addTokenParserBroker(Twig_TokenParserBroker $broker) + public function addTokenParserBroker(self $broker) { $this->brokers[] = $broker; } - public function removeTokenParserBroker(Twig_TokenParserBroker $broker) + public function removeTokenParserBroker(self $broker) { if (false !== $pos = array_search($broker, $this->brokers)) { unset($this->brokers[$pos]); @@ -80,7 +82,7 @@ class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface * * @param string $tag A tag name * - * @return null|Twig_TokenParserInterface A Twig_TokenParserInterface or null if no suitable TokenParser was found + * @return TokenParserInterface|null A Twig_TokenParserInterface or null if no suitable TokenParser was found */ public function getTokenParser($tag) { diff --git a/system/libs/Twig/TokenParserBrokerInterface.php b/system/libs/Twig/Twig/TokenParserBrokerInterface.php old mode 100755 new mode 100644 similarity index 73% rename from system/libs/Twig/TokenParserBrokerInterface.php rename to system/libs/Twig/Twig/TokenParserBrokerInterface.php index 6c93f5ea..f369264d --- a/system/libs/Twig/TokenParserBrokerInterface.php +++ b/system/libs/Twig/Twig/TokenParserBrokerInterface.php @@ -10,6 +10,8 @@ * file that was distributed with this source code. */ +use Twig\TokenParser\TokenParserInterface; + /** * Interface implemented by token parser brokers. * @@ -26,19 +28,19 @@ interface Twig_TokenParserBrokerInterface * * @param string $tag A tag name * - * @return Twig_TokenParserInterface|null A Twig_TokenParserInterface or null if no suitable TokenParser was found + * @return TokenParserInterface|null A Twig_TokenParserInterface or null if no suitable TokenParser was found */ public function getTokenParser($tag); /** - * Calls Twig_TokenParserInterface::setParser on all parsers the implementation knows of. + * Calls Twig\TokenParser\TokenParserInterface::setParser on all parsers the implementation knows of. */ public function setParser(Twig_ParserInterface $parser); /** * Gets the Twig_ParserInterface. * - * @return null|Twig_ParserInterface A Twig_ParserInterface instance or null + * @return Twig_ParserInterface|null A Twig_ParserInterface instance or null */ public function getParser(); } diff --git a/system/libs/Twig/Twig/TokenParserInterface.php b/system/libs/Twig/Twig/TokenParserInterface.php new file mode 100644 index 00000000..800c9719 --- /dev/null +++ b/system/libs/Twig/Twig/TokenParserInterface.php @@ -0,0 +1,11 @@ + */ -class Twig_SimpleFilter +class TwigFilter { protected $name; protected $callable; protected $options; - protected $arguments = array(); + protected $arguments = []; - public function __construct($name, $callable, array $options = array()) + public function __construct($name, $callable, array $options = []) { $this->name = $name; $this->callable = $callable; - $this->options = array_merge(array( + $this->options = array_merge([ 'needs_environment' => false, 'needs_context' => false, 'is_variadic' => false, @@ -35,10 +39,10 @@ class Twig_SimpleFilter 'is_safe_callback' => null, 'pre_escape' => null, 'preserves_safety' => null, - 'node_class' => 'Twig_Node_Expression_Filter', + 'node_class' => '\Twig\Node\Expression\FilterExpression', 'deprecated' => false, 'alternative' => null, - ), $options); + ], $options); } public function getName() @@ -76,14 +80,14 @@ class Twig_SimpleFilter return $this->options['needs_context']; } - public function getSafe(Twig_Node $filterArgs) + public function getSafe(Node $filterArgs) { if (null !== $this->options['is_safe']) { return $this->options['is_safe']; } if (null !== $this->options['is_safe_callback']) { - return call_user_func($this->options['is_safe_callback'], $filterArgs); + return \call_user_func($this->options['is_safe_callback'], $filterArgs); } } @@ -118,4 +122,7 @@ class Twig_SimpleFilter } } -class_alias('Twig_SimpleFilter', 'Twig\TwigFilter', false); +class_alias('Twig\TwigFilter', 'Twig_SimpleFilter'); + +// Ensure that the aliased name is loaded to keep BC for classes implementing the typehint with the old aliased name. +class_exists('Twig\Node\Node'); diff --git a/system/libs/Twig/SimpleFunction.php b/system/libs/Twig/TwigFunction.php old mode 100755 new mode 100644 similarity index 77% rename from system/libs/Twig/SimpleFunction.php rename to system/libs/Twig/TwigFunction.php index a6aa7ca7..374f0707 --- a/system/libs/Twig/SimpleFunction.php +++ b/system/libs/Twig/TwigFunction.php @@ -9,6 +9,10 @@ * file that was distributed with this source code. */ +namespace Twig; + +use Twig\Node\Node; + /** * Represents a template function. * @@ -16,27 +20,27 @@ * * @author Fabien Potencier */ -class Twig_SimpleFunction +class TwigFunction { protected $name; protected $callable; protected $options; - protected $arguments = array(); + protected $arguments = []; - public function __construct($name, $callable, array $options = array()) + public function __construct($name, $callable, array $options = []) { $this->name = $name; $this->callable = $callable; - $this->options = array_merge(array( + $this->options = array_merge([ 'needs_environment' => false, 'needs_context' => false, 'is_variadic' => false, 'is_safe' => null, 'is_safe_callback' => null, - 'node_class' => 'Twig_Node_Expression_Function', + 'node_class' => '\Twig\Node\Expression\FunctionExpression', 'deprecated' => false, 'alternative' => null, - ), $options); + ], $options); } public function getName() @@ -74,17 +78,17 @@ class Twig_SimpleFunction return $this->options['needs_context']; } - public function getSafe(Twig_Node $functionArgs) + public function getSafe(Node $functionArgs) { if (null !== $this->options['is_safe']) { return $this->options['is_safe']; } if (null !== $this->options['is_safe_callback']) { - return call_user_func($this->options['is_safe_callback'], $functionArgs); + return \call_user_func($this->options['is_safe_callback'], $functionArgs); } - return array(); + return []; } public function isVariadic() @@ -108,4 +112,7 @@ class Twig_SimpleFunction } } -class_alias('Twig_SimpleFunction', 'Twig\TwigFunction', false); +class_alias('Twig\TwigFunction', 'Twig_SimpleFunction'); + +// Ensure that the aliased name is loaded to keep BC for classes implementing the typehint with the old aliased name. +class_exists('Twig\Node\Node'); diff --git a/system/libs/Twig/SimpleTest.php b/system/libs/Twig/TwigTest.php old mode 100755 new mode 100644 similarity index 74% rename from system/libs/Twig/SimpleTest.php rename to system/libs/Twig/TwigTest.php index fee5778b..5054965f --- a/system/libs/Twig/SimpleTest.php +++ b/system/libs/Twig/TwigTest.php @@ -9,6 +9,8 @@ * file that was distributed with this source code. */ +namespace Twig; + /** * Represents a template test. * @@ -16,22 +18,24 @@ * * @author Fabien Potencier */ -class Twig_SimpleTest +class TwigTest { protected $name; protected $callable; protected $options; - public function __construct($name, $callable, array $options = array()) + private $arguments = []; + + public function __construct($name, $callable, array $options = []) { $this->name = $name; $this->callable = $callable; - $this->options = array_merge(array( + $this->options = array_merge([ 'is_variadic' => false, - 'node_class' => 'Twig_Node_Expression_Test', + 'node_class' => '\Twig\Node\Expression\TestExpression', 'deprecated' => false, 'alternative' => null, - ), $options); + ], $options); } public function getName() @@ -68,6 +72,16 @@ class Twig_SimpleTest { return $this->options['alternative']; } + + public function setArguments($arguments) + { + $this->arguments = $arguments; + } + + public function getArguments() + { + return $this->arguments; + } } -class_alias('Twig_SimpleTest', 'Twig\TwigTest', false); +class_alias('Twig\TwigTest', 'Twig_SimpleTest'); diff --git a/system/libs/Twig/Util/DeprecationCollector.php b/system/libs/Twig/Util/DeprecationCollector.php index c7bf53be..09917e92 100644 --- a/system/libs/Twig/Util/DeprecationCollector.php +++ b/system/libs/Twig/Util/DeprecationCollector.php @@ -9,17 +9,23 @@ * file that was distributed with this source code. */ +namespace Twig\Util; + +use Twig\Environment; +use Twig\Error\SyntaxError; +use Twig\Source; + /** * @author Fabien Potencier * * @final */ -class Twig_Util_DeprecationCollector +class DeprecationCollector { private $twig; private $deprecations; - public function __construct(Twig_Environment $twig) + public function __construct(Environment $twig) { $this->twig = $twig; } @@ -34,32 +40,32 @@ class Twig_Util_DeprecationCollector */ public function collectDir($dir, $ext = '.twig') { - $iterator = new RegexIterator( - new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::LEAVES_ONLY + $iterator = new \RegexIterator( + new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($dir), \RecursiveIteratorIterator::LEAVES_ONLY ), '{'.preg_quote($ext).'$}' ); - return $this->collect(new Twig_Util_TemplateDirIterator($iterator)); + return $this->collect(new TemplateDirIterator($iterator)); } /** * Returns deprecations for passed templates. * - * @param Traversable $iterator An iterator of templates (where keys are template names and values the contents of the template) + * @param \Traversable $iterator An iterator of templates (where keys are template names and values the contents of the template) * * @return array An array of deprecations */ - public function collect(Traversable $iterator) + public function collect(\Traversable $iterator) { - $this->deprecations = array(); + $this->deprecations = []; - set_error_handler(array($this, 'errorHandler')); + set_error_handler([$this, 'errorHandler']); foreach ($iterator as $name => $contents) { try { - $this->twig->parse($this->twig->tokenize(new Twig_Source($contents, $name))); - } catch (Twig_Error_Syntax $e) { + $this->twig->parse($this->twig->tokenize(new Source($contents, $name))); + } catch (SyntaxError $e) { // ignore templates containing syntax errors } } @@ -67,7 +73,7 @@ class Twig_Util_DeprecationCollector restore_error_handler(); $deprecations = $this->deprecations; - $this->deprecations = array(); + $this->deprecations = []; return $deprecations; } @@ -83,4 +89,4 @@ class Twig_Util_DeprecationCollector } } -class_alias('Twig_Util_DeprecationCollector', 'Twig\Util\DeprecationCollector', false); +class_alias('Twig\Util\DeprecationCollector', 'Twig_Util_DeprecationCollector'); diff --git a/system/libs/Twig/Util/TemplateDirIterator.php b/system/libs/Twig/Util/TemplateDirIterator.php index c8682335..1ab0dac5 100644 --- a/system/libs/Twig/Util/TemplateDirIterator.php +++ b/system/libs/Twig/Util/TemplateDirIterator.php @@ -9,10 +9,12 @@ * file that was distributed with this source code. */ +namespace Twig\Util; + /** * @author Fabien Potencier */ -class Twig_Util_TemplateDirIterator extends IteratorIterator +class TemplateDirIterator extends \IteratorIterator { public function current() { @@ -25,4 +27,4 @@ class Twig_Util_TemplateDirIterator extends IteratorIterator } } -class_alias('Twig_Util_TemplateDirIterator', 'Twig\Util\TemplateDirIterator', false); +class_alias('Twig\Util\TemplateDirIterator', 'Twig_Util_TemplateDirIterator'); diff --git a/system/twig.php b/system/twig.php index 9f484c7d..9ab2e509 100644 --- a/system/twig.php +++ b/system/twig.php @@ -1,10 +1,13 @@ CACHE . 'twig/', 'auto_reload' => $dev_mode, @@ -12,31 +15,31 @@ $twig = new Twig_Environment($twig_loader, array( )); if($dev_mode) { - $twig->addExtension(new Twig_Extension_Debug()); + $twig->addExtension(new Twig_DebugExtension()); } unset($dev_mode); -$function = new Twig_SimpleFunction('getStyle', function ($i) { +$function = new TwigFunction('getStyle', function ($i) { return getStyle($i); }); $twig->addFunction($function); -$function = new Twig_SimpleFunction('getLink', function ($s) { +$function = new TwigFunction('getLink', function ($s) { return getLink($s); }); $twig->addFunction($function); -$function = new Twig_SimpleFunction('getPlayerLink', function ($s, $p) { +$function = new TwigFunction('getPlayerLink', function ($s, $p) { return getPlayerLink($s, $p); }); $twig->addFunction($function); -$function = new Twig_SimpleFunction('getGuildLink', function ($s, $p) { +$function = new TwigFunction('getGuildLink', function ($s, $p) { return getGuildLink($s, $p); }); $twig->addFunction($function); -$function = new Twig_SimpleFunction('hook', function ($hook) { +$function = new TwigFunction('hook', function ($hook) { global $hooks; if(is_string($hook)) { @@ -47,18 +50,18 @@ $function = new Twig_SimpleFunction('hook', function ($hook) { }); $twig->addFunction($function); -$function = new Twig_SimpleFunction('config', function ($key) { +$function = new TwigFunction('config', function ($key) { return config($key); }); $twig->addFunction($function); -$function = new Twig_SimpleFunction('getCustomPage', function ($name) { +$function = new TwigFunction('getCustomPage', function ($name) { $success = false; return getCustomPage($name, $success); }); $twig->addFunction($function); -$filter = new Twig_SimpleFilter('urlencode', function ($s) { +$filter = new TwigFilter('urlencode', function ($s) { return urlencode($s); });